Creating an iPhone Application

OSXDEV

Jump to: navigation, 찾기

목차

[편집] Creating an iPhone Application

상위 레벨에서 보면, iPhone용 어플리케이션을 개발하는 과정은 Mac OS X용 어플리케이션을 개발하는 것과 유사하다. 둘 모두 동일한 툴과 다수의 동일한 기본 라이브러리를 사용한다. 이러한 유사성에도 불구하고, 큰 차이점 역시 존재한다. iPhone은 데스크탑 컴퓨터가 아니다; iPhone은 데스크탑과 다른 용도를 가지고 잇으며 디자인 관점에서 다른 접근법을 필요로 한다. 이런 접근법에서는 iPhoneOS의 강점을 부각시키고, 모바일 환경에서는 일상적이지 않거나 실용적이지 않은 기능들을 배제할 필요가 있다. iPhone과 iPod touch의 작은 화면 크기 때문에 여러분의 어플리케이션의 유저 인터페이스를 조직적으로 잘 구성하고 항상 사용자가 가장 원하는 정보에 집중할 수 있도록 해야 한다.

iPhoneOS는 데스크탑에서는 불가능한 방법으로 iPhone과 iPod touch를 조작할 수 있도록 한다. 멀티 터치 인터페이스는 일정을 받기 위한 혁명적인 방법을 제공한다. 스크린을 터치한 여러 손가락으로 보고를 하고, 멀티 핑커 제스처를 처리하거나 기타 복잡한 입력도 쉽게 처리할 수 있다. 또한, 몇몇 데스크탑은 이미 탑재하고 있는 기능이기는 하지만, 가속도 센서와 같은 내장된 하드웨어 기능은 iPhone OS에서 스크린의 현재 방향을 추적하고 이 방향에 맞춰 컨텐츠를 조정하는 등의 확장된 동작을 제공하는데 유용하게 사용할 수 있다. 이러한 기능들을 다루는 방법을 이해한다면 여러분은 사용자가 원하는 디자인을 하는데 집중할 수 있도록 도움이 될 것이다.

iPhone 어플리케이션의 디자인을 이해하기 위한 가장 좋은 방법은 예제를 통해서 알아보는 것이다. 이 글을 MoveMe라는 예제 프로그램을 통해 iPhone의 어플리케이션 디자인에 대해 알아볼 것이다. 이 예제는 다음과 같은 iPhone 어플리케이션의 전형적인 동작들에 대해서 보여줄 것이다.

  • 어플리케이션의 초기화
  • 윈도우의 표시
  • 사용자 정의 컨텐츠를 그리기
  • 터치 이벤트를 처리하기
  • 애니메이션 처리하기

그림 1에서는 이 어플리케이션의 인터페이스를 보여준다.

그림:k_cct_iphone_create_moveme.png

그림 1 The MoveMe application window

Welcome 버튼을 터치하면 이 버튼은 사용자의 손가락의 위치에 맞춰 가운데로 정렬한 뒤 맥동하게 된다. 만일 여러분이 손가락을 화면을 따라 드래그하게 되면 이 버튼을 손가락을 따라서 움직인다. 손가락을 화면에서 떼면 맥동 애니메이션이 아닌 다른 애니메이션을 이용해서 버튼을 원래 위치로 돌아온다. 버튼 밖의 아무 곳이나 더블 태핑을 한다면, 환영의 의미를 갖는 다른 언어로 버튼의 글귀를 바꾸게 된다.

이 글의 다른 섹션을 읽기 전에 여러분은 MoveMe 샘플 어플리케이션을 다운로드 받는 것이 좋다. 그래야만 글을 읽어가면서 소스 코드를 직접 참조할 수 있기 때문이다. 또한, iPhone OS과 개발 툴 및 개발 언어에 대해 기본 지식을 얻기 위해서 다음의 문서들을 iPhone Dev Center에서 미리 읽어보는 것이 좋다.

만일 Objective-C에 대해서 익숙하지 않다면, Learning Objective-C: A Primer를 미리 읽어두는 편이 Objective-C의 기본적인 구문에 대해서 이해하기 쉬울 것이다.

[편집] Examining the MoveMe Sample Project

MoveMe 샘플에는 소스 코드 및 어플리케이션을 빌드하고 실행하는데 필요한 파이들이 포함되어 있다. iPhone OS용 프로젝트는 Xcode(기본 설치 위치는 /Developer/Applications)를 사용해서 관리할 수 있다. 각각의 Xcode 프로젝트 윈도우는 코드와 리소스 파일을 그러모은 workspace, 소스 코드를 컴파일하고 어플리케이션을 어셈블링하기 위한 빌드 규칙, 소스 코드를 편집하고 디버깅하기 위한 툴들을 결합한다.

그림 2는 MoveMe 어플리케이션의 Xcode 프로젝트 윈도우이다. 프로젝트를 열려면 MoveMe 프로젝트를 로컬 하드 드라이브에 복사하고, MoveMe.xcodeproj 파일을 더블클릭하면 된다. 또는 Xcode에서 파File > Open 메뉴를 실행하여 파일을 선택해도 된다. 이 프로젝트는 다수의 Objective-C 소스 파일(확장자 .m)와 이미지 파일과 리소스 파일, 그리고 어플리케이션 번들을 빌드하기 위한 미리 정의된 MoveMe 타켓을 포함하고 있다.

그림:k_cct_create_movemeproject.png

그림 2 The MoveMe project window

iPhone OS에서 Xcode 프로젝트의 최종 타겟은 어플리케이션 번들(application bundle)이다. 어플리케이션 번들은 어플리케이션의 바이너리 실행 파일과 이를 위한 리소스 파일들을 포함하는 특수한 형태의 디렉토리이다. iPhone OS의 번들은 대부분의 파일이 번들 디렉토리의 최상위 수준에 있는 상대적으로 flat directory 구조를 가지고 있다. 그러나, 번들은 로컬라이즈 버전을 위한 문자열과 언어 전용의 리소스 파일을 저장하기 위해 서브 디렉토리들을 포함하고 있기도 한다. 이 글의 목적 상 어플리케이션 번들의 정확한 구조는 알 필요는 없지만, 관심이 있다면, iPhone OS Programming Guide"The Application Bundle"에서 관련 정보를 찾아 볼 수 있다.

[편집] MoveMe 빌드하기

MoveMe를 빌드하고, 시뮬레이터에서 실행하라면 다음의 과정을 수행하면 된다.

1. Xcode에서 MoveMe.xcodeproj 파일을 연다.
2. 프로젝트 툴바에서 Active SDK 메뉴에 시뮬레이터 옵션이 선택되어 있는지를 확인한다.
3. 메뉴에서 Build > Build and Go(Run)를 선택하거나, 툴바에서 Build and Go 버튼을 클릭한다.

어플리케이션의 빌드가 끝나면, Xcode는 시뮬레이터에 어플리케이션을 로드하고 실행한다. 마우스를 써서, Welcome 버튼을 클릭하거나 어플리케이션의 동작을 보기 위해서 스크린 주변을 드래그할 수 있다. 장비를 개발용으로 셋팅해 두었다면, 어플리케이션을 빌드해서 그 장비에서 실행할 수도 있다. 장비를 개발용으로 셋팅하고 어플리케이션을 로드하기 위한 방법은 iPhone OS Programming Guide"Development Environment"에서 참고하라.

[편집] 메모리 관리에 관한 이야기

iPhone OS는 기본적으로 객체 지향 시스템이다. 그래서, 여러분이 할당한 메모리의 대부분은 Objective-C 객체의 형태를 띄고 있다. IPhone OS의 객체는 객체에 의해 점유하고 있는 메모리를 안전하게 해제하기 위해서 레퍼런스 카운팅 방법을 사용한다. 객체가 처음 생성되었을 때 레퍼런스 카운트는 1이다. 이 객체를 받는 클라이언트는 객체를 retain 할 수 있다. 그러면, 객체의 레퍼런스 카운트가 1 증가한다. 클라이언트가 객체를 retain 한 경우, 객체가 더 이상 필요없게 되면 클라이언트는 반드시 객체를 release 해야 한다. 객체를 release 하면 레퍼런스 카운트가 1 감소한다. 레퍼런스 카운트가 0이 되면, 시스템은 객체가 점유하고 있던 메모리를 자동적으로 회수한다.


iPhone OS는 Mac OS 10.5(혹은 이후 버전)에서 지원하는 가베지 콜렉션 기능에 의한 메모리 관리는 지원하지 않는다.


만일 일반적인 메모리 블럭 -객체에 할당되지 않은 메모리 블럭- 을 할당하기 원한다면, 표준 malloc 라이브러리를 호출하면 된다. malloc에 의해 할당된 메모리는 필요없어졌을 때 free 함수를 호출하여 직접 메모리를 반환해야 할 책임이 여러분에게 있다. 시스템은 malloc으로 할당된 메모리 블럭을 회수하지 않는다.

메모리를 할당한 방법과는 관계없이 메모리 사용량을 관리하는 것은 Mac OS X에 비해서 iPhone OS에서는 더 중요한 일이다. iPhone OS가 가상 메모리 시스템을 지원하지만, 스왑 파일은 지원하지 않는다. 이는 코드 페이지는 필요에 따라서 플러쉬 될 수 있지만, 어플리케이션의 모든 데이터는 메모리에 상주해야 함을 의미한다. 시스템은 여유 메모리의 전체 사용량을 감시하여, 어플리케이션이 필요로 하는 메모리를 할당해 준다. 메모리 사용량이 극단적으로 치닫는 경우, 시스템은 어플리케이션을 강제 종료 시킬 수 있다. 그러나 이러한 동작은 전화를 받는 것과 같은 중요한 작업을 처리하기 위해 충분한 메모리를 확보하기 위한 최후의 수단일 뿐이다.

iPhoneOS에서의 메모리를 할당하는 방법에 대한 좀 더 자세한 내용은 Cocoa Fundamentals Guide를 참고하라. 여러분의 어플리케이션의 메모리 사용량을 개선하기 위한 방법에 대한 정보나 팁은 iPhone OS Programming Guide"Managing Your Memory Usage"를 참고하면 된다.

[편집] MoveMe 어플리케이션의 초기화

C 언어 기반의 어플리케이션이 그렇듯이 모든 iPhone용 어플리케이션의 진입점(entry point)는 main 함수이다. 한가지 좋은 소식은 Xcode의 iPhone 템플릿으로 새 프로젝트를 생성할 때 굳이 main 함수를 직접 작성할 필요가 없다는 것이다. 프로젝트 템플릿은 어플리케이션을 실행하는데 필요한 모든 코드를 포함한 함수를 포함하고 있기 때문이다.

리스트 1은 MoveMe 어플리케이션의 main 함수이다. main 함수는 프로젝트의 main.m 파일에 있다. 모든 생성된 어플리케이션은 대체로 아래의 함수와 같은 형태를 갖게 된다. 이 함수는 두 가지 중요한 작업을 한다. 첫째, Objective-C 객체가 autorelease 메소드로 메모리에서 해제되도록 메모리 회수의 역할을 담당하는 어플리케이션의 최상위 autorelease 풀을 생성한다. 두번째는 MoveMe 어플리케이션의 key object들을 생성 및 초기화하고 이벤트 핸들링 루트를 시작하는 UIApplicationMain 함수를 호출한다. 이 함수는 어플리케이션을 종료할 때 리턴된다.

Listing 1 Using the provided main function

int main(int argc, char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc[ init] ;
int retVal = UIApplicationMain(argc, argv, nil, @"MoveMeAppDelegate");
[pool release] ;
return retVal ;
}

여러분 자신의 프로젝트에서 main 함수에서 실제로 관심을 기울여야 할 부분은 application delegate object의 이름이다. 이 이름은 여러분의 프로젝트에서 여러분이 작성해야하는 클래스의 이름이다. application delegate object의 역할은 UIApplication 객체와 함께 어플리케이션의 상태 변화에 대응하는 것이다. 어플리케이션 객체의 대부분의 작업들을 처리하지만, 딜리게이트 객체는 다음과 같은 몇몇 중요한 역할을 수행해야 한다.

  • 어플리케이션의 윈도우를 생성하고, 유저 인터페이스를 초기화한다.
  • 사용자 정의 데이터 엔진을 위한 추가적인 초기화 작업을 수행한다.
  • 어플리케이션의 사용자 정의 URL과 연결된 컨텐츠를 오픈한다.
  • 장비의 기울임 방향의 변화에 맞춰 반응한다.
  • 메모리 부족 경고에 대처한다.
  • 시스템에 의해 발생한 어플리케이션 종료 요청을 처리한다.

어플리케이션이 런칭되었을 때 딜리게이트 객체가 즉시 중점을 두는 것은 어플리케이션 윈도우를 생성하는 것과 #어플리케이션 윈도우 생성하기에 기술되어 있는 대로 이 윈도우를 사용자에게 보여주는 것이다. 또한, 딜리게이트 객체는 어플리케이션의 이전 상태를 복구하거나 필요한 객체들을 생성하는 등 어플리케이션을 즉시 사용할 수 있도록 필요한 작업들을 처리한다. 어플리케이션이 종료되면, 딜리게이트 객체는 어플리케이션이 정상적으로 셧다운되도록 처리하고, 다음 런칭 사이클에서 사용할 정보들을 보존해야 한다.

iPhone 어플리케이션의 라이프 사이클과 기본 아키텍처에 대한 자세한 정보는 iPhone OS Programming Guide"Core Application Architecture"를 참고하라.

[편집] 어플리케이션 윈도우 생성하기

모든 어플리케이션은 전체 화면에 맞추어 윈도우를 생성하고 이 윈도 내부를 채울 책임을 갖는다. iPhone OS에서 동작하는 그래픽 기반의 어플리케이션은 다른 어플리케이션과 함께 나란히 실행되지 않는다. 사실, 커널과 소수의 로우 레벨 시스템 데몬을 제외하고는 유일하게 여러분의 어플리케이션만이 런치된 이후에 실행된다. 뿐만 아니라, 여러분의 어플리케이션은 한개 이상의 윈도우 - UIWindow 클래스의 인스턴스인 -를 요구할 수 없다. 유저 인터페이스의 변화가 필요할 경우에는 윈도우에 의해 표시되는 뷰를 교체해야 한다.

윈도우는 유저 인터페이스를 위한 드로잉 서페이스를 제공하지만, 실제 컨텐트를 제공하는 것은 뷰 객체이다. 뷰 객체는 UIView 클래스의 인스턴스이며, 컨텐츠를 드로우하며 사용자의 요청에 반응하게 된다. 여러분은 여러분의 윈도우의 어떤 형태의 뷰도 추가할 수 있으며, 사용자 정의 드로잉 및 이벤트 핸들링을 구현하기 위해 UIView를 상속한 커스텀 뷰 클래스를 정의할 수 있다. MoveMe 어플리케이션은 어플리케이션의 인터페이스를 표시하고, 사용자 요청을 처리하기 위해 두 개의 뷰를- 하나는 MyView 클래스이며, 또 다른 하나는 PlacardView 클래스이다 - 구현한다.


iPhone SDK의 초기 베타 버전에서는 여러분은 어플리케이션 윈도우와 뷰를 코드 상에서 구현해야만 한다. 그러나, 최종 릴리즈 버전에서는 인터페이스 빌더를 이용해서 어플리케이션 윈도우와 뷰를 작성할 수 있을 것이다. 인터페이스 빌더는 뷰를 윈도우내에 생성하거나 배치할 수 있으며, view hierarchy를 구축하고, 뷰의 옵션을 정의하고, 뷰와 어플리케이션의 다른 객체들의 relationship을 지정하기 위한 비주얼 툴이다. 인터페이스 빌더가 비주얼 툴이기 때문에 일련의 작업을 윈도우 위에서 컴포넌트들을 드래깅하면서 처리할 수 있고, 따라서 여러분은 인터페이스를 수정한 뒤 수정 결과를 즉시 확인할 수 있다.


어플리케이션이 런칭되었을 때 처리해야 할 작업은 어플리케이션 윈도우를 생성한 뒤 가능한 빨리 첫 컨텐트를 표시하는 것이다. 윈도우를 생성하는 작업은 application delegate 객체의 담당이다. 어플리케이션이 런칭 상태를 마치고 이벤츠를 처리할 수 있는 준비 상태가 되었을 때, UIApplication 객체는 applicationDidFinishLaunching: 메시지를 딜리게이트에게 보낸다. 이 메시지가 의미하는 바는 딜리게이트가 윈도우를 생성하고 어플리케이션에게 필요한 초기화 작업들을 처리해야 할 시기가 되었다는 것이다.

MoveMe 어플리케이션에서 딜리게이트의 applicationDidFinishLaunching: 메소드는 다음과 같은 작업을 수행한다.

1. 스크린의 크기와 같은 프레임 크기를 갖는 UIWindow 객체를 새로 생성한다.
2. 윈도우의 전체를 채우고 배경의 역할을 하는 MyView 클래스의 인스턴스를 생성한다.
3. 배경 윈도우의 중앙에 위치할 Welcome 버튼의 역할을 하는 PlacardView 클래스의 인스턴스를 생성한다.
4. 윈도우를 표시한다.

리스트 2는 MoveMe 어플리케이션의 applicationDidFinishLaunching: 메소드이다. 이 메소드에서는 UIScreen 클래스를 사용하여 화면의 크기를 파악하고, 이 크기에 맞춰서 UIWindow 객체를 생성하고 초기화 한다. 이 객체는 딜리게이트 객체에 window 멤버 변수로 저장된다. 그리고, 메인 컨텐트 뷰를 생성하고 윈도우를 화면에 표시한다. 윈도우가 화면에 표시된다는 것은 여러분의 어플리케이션이 이벤트 처리를 할 준비가 되었다는 것을 의미한다.

Listing 2 Creating the application window

- (void)applicationDidFinishLaunching:(UIApplication *)application
{
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds] ;
// Set up content view to fill screen
contentView = [[MyView alloc] initWithFrame:[window bounds]] ;
// Set up and show window
[window addSubview:contentView] ;
[window makeKeyAndvisible];
}

applicationDidFinishLaunching: 메소드는 어플리케이션의 유저 인터페이스를 생성하는 작업 이외의 용도로도 사용할 수 있다. 많은 어플리케이션들이 필요한 데이터 구조를 초기화하거나, 사용자 설정을 로드하거나, 최근의 어플리케이션이 종료된 상태로 복귀하는 등의 작업을 처리한다.


위의 코드는 윈도우를 생성하고, 배경 뷰를 생성하고, 윈도우를 화면을 표시하지만, Welcome 버튼을 표시할 PlacardView 클래스를 생성하는 코드는 존재하지 않는다. 이 작업은 MyView 클래스의initWithFrame: 메소드에서 처리되며, 이는 리스트 3에 나타나있다. 뷰 객체의 초기화는 PlacardView 객체의 생성을 포함한다. MyView 클래스가 어플리케이션의 전체 배경을 담당하기 때문에 MyView는 PlacardView를 subview 객체로 등록하게 된다. 이 두 뷰의 relationship은 어플리케이션의 배경위에 Welcome 버튼을 표시하는 것 뿐만 아니라 버튼이 처리해야 할 이벤트를 MyView에서 처리할 수 있도록 해준다.

Listing 3 Initializing the content view

- initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
{
self.backgroundColor = [UIColor darkGrayColor] ;
// Create the placard view -- it calculates its own frame based on its image
placardView = [[PlacardView alloc] init] ;
placardView.center = self.center ;
[self addsubview:placardView];
}
return self ;
}

윈도우와 뷰의 생성에 대한 더 자세한 정보는 iPhone OS Programming Guide"Windows and Views"를 참고하라.