본문 바로가기

iOS Programming

ObjectiveC 초간단 훑어보기

생업에 종사하다 보니 모든 우선순위가 현재 제가 맡은 개발 업무에만 집중되고 있습니다.

그러다보니 스터디도 더디고, 그에 따라 카페만 만들어 놓고 강좌도 못올리고 ㅠㅠ

 

오늘은 Xcode에서 새로운 프로젝트를 만들 때 자동으로 생성해 주는 소스를 분석하는 방법으로 iPhone 어플리케이션의 개발 언어인 ObjectiveC를 간단하게 살펴보았습니다. 보다 체계적이고 상세한 공부를 위해서는 ObjectiveC 전문 서적으로 스터디해야 하겠지만,…

필자가 C/C++ 개발자이다 보니 C/C++과 하는 방법도 이용했으며, 일부 iPhone SDK의 내용도 다루었습니다.

 

여기에서 사용된 프로젝트는 View Based Application이며 그 이름을 VBApp로 명명하였습니다.

 

Xcode를 이용해 만들어진 프로젝트의 파일들을 살펴보면, *.h, *.m *.xib 파일들이 눈에 들어 옵니다. *.h 파일은 클래스를 선언하는 헤더 파일이고, *.m은 클래스의 프로퍼티와 메서드 등을 정의하는, C./C++에서 *.cpp와 같은 역할을 하는 파일입니다. 그리고 *.xib 파일은 Interface Builder에서 사용되는 파일로 UI 리소스 파일입니다. 그럼 우선 main.m 파일에 대해 먼저 살펴보겠습니다.

 

#import <UIKit/UIKit.h>

 

int main(int argc, char *argv[]) {

   

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    int retVal = UIApplicationMain(argc, argv, nil, nil);

    [pool release];

    return retVal;

}

 

 

첫 번째 줄 #import는 다른 헤더파일을 포함하는 지시자로 C/C++에서의 #include와 동일한 개념입니다.

 

 

int main(int argc, char *argv[])

iPhone 어플리케이션의 시작은 main() 함수로 시작됩니다. 이 역시 C/C++의 내용과 같으며 파라미터 또한 동일한 방식으로 전달됩니다.

 

 

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

이 라인은 C/C++ 지식으로는 도저히 해석이 되지 않는 라인이었습니다.

하나 하나, 차근차근 살펴보겠습니다.

우선 C/C++에서는 연산의 우선 순위를 괄호()로 결정하지만 ObjectiveC에서는 대괄호[]로 연산의 우선 순위를 결정합니다.

ObjectiveC에서의 메서드 호출을 messaging(이벤트와는 전혀 관계없는 용어입니다.)이라고 하는데 그 호출 방법이 다음과 같습니다.

 

    오브젝트클래스명 메서드;

파라미터 전달에 대해서는 다음 기회에 정리하겠습니다.

결국 위 라인을 C/C++ 형식으로 표현해 보면 아래와 갔습니다.

    NSAutoreleasePool * pool = ((NSAutoreleasePool::alloc())->init();

 

그럼 이 라인에서 사용된 SDK에 대해 알아 보겠습니다. 사실 이 부분은 iPhone SDK 내용이 아닌 맥용어플리케이션 개발에서 사용되는 코코아 개발 플랫폼에 속한 내용으로 보아야 합니다. 그 발 플랫폼이 iPhone 개발 영역으로 자연스럽게 전이된 것입니다. Visual C++ MFC 라이브러리를 그대로 스마트폰 플랫폼 개발에 이용이 가능한 것과 같은 내용입니다.

 

우선 NSAutoreleasePool 클래스에 대해 살펴보겠습니다. NSAutoreleasePool은 해당 어플리케이션에서 동적으로 생성되고 사용되는 모든 오브젝트들을 관리하기 위한 메모리 풀이라고 보시면 되겠습니다. ObjectiveC에서 클래스를 생성하고 사용하기 위해서는 반드시 해당 쓰레드별로 NSAutoreleasePool를 먼저 생성해야 합니다.

 

alloc 메서드는 NSAutoreleasePool의 상위 클래스인 NSObject class method입니다.

init 메서드는 NSAutoreleasePool의 상위 클래스인 NSObject instance method입니다.

 

ObjectiveC에서는 클래스의 메서드를 class method instance method로 구분됩니다.

class method C/C++에서의 정적함수를 의미하고 instance method는 일반함수를 의미합니다.

또한 코코아 프로그래밍에서 제공하는 클래스 중 NS로 시작되는 모든 클래스는 NSObject로부터 상속받습니다. alloc init 메서드는 NSObject의 매서드로 alloc 메서는 클래스를 생성하여 생성된 오브젝트의 인스턴스 포인터를 리턴하고, init 메서드는 오브젝트 메모리를 초기화하고 해당 오브젝트의 인스턴스 포인터를 다시 리턴합니다.

alloc init 메서드의 선언을 살펴보면 id라는 데이터타입을 리턴하도록 되어 있습니다. id 타입은 ObjectiveC에서 사용되는 오브젝트들을 가리키는 구조체입니다.

 

 

    int retVal = UIApplicationMain(argc, argv, nil, nil);

 

이 함수가 호출되면 Application Object와 Application Delegate를 생성하고 이벤트 핸들러 루프로 진입합니다.

Application Delegate는 iPhone OS로 부터 발생되는 시스템 이벤트를 해당 어플리케이션으로 전달하는 역할을 합니다. Application Delegate에 대해서는 나중에 살펴보기로 하구요. UIApplicationMain( )에서 앞 두 파라미터는 main( )에서 전달받은 파라미터를 그대로 전달하면 되고 세 번째 인자는 UIApplication으로 부터 상속된 클래스가 있을 경우, 해당 클래스의 이름을 넘기는데, 일반적으로 nil이 사용되면 어플리케이션 오브젝트로 UIApplication 클래스가 생성됩니다. 그리고 마지막 인자는 Application Delegate로 사용될 클래스의 이름을 넘기는데 nil을 지정하면 Main Nib로 지정된 오브젝트가 Application Delegate로 사용됩니다. Main Nib는 프로젝트 속성에서 지정할 수 있습니다. (Project 메뉴의 Edit Active Target... / Properties) 그리고 nil 키워드는 C/C++에서의 '\0'(NULL)을 의미합니다.



    [pool release];

    return retVal;

 

어플리케이션이 종료되면 이벤트 루프를 빠져나오고 위의 코드가 실행됩니다. NSAutoreleasePool 오브젝트를 해제하고 UIApplicationMain( )의 리턴값을 그대로 리턴합니다.




다음은 Application Delegate의 선언과 정의를 살펴보겠습니다.


#import <UIKit/UIKit.h>

@class VBAppViewController;

@interface VBAppAppDelegate : NSObject <UIApplicationDelegate> {
    UIWindow *window;
    VBAppViewController *viewController;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet VBAppViewController *viewController;

@end

 


위 골격을 기반으로 ObjectiveC에서의 class을 일반적인 선언방법을 살펴보겠습니다.


@class 클래스명;                          // 클래스 참조 선언

// 클래스의 선언 시작
@interface 클래스명 : 상속클래스명 <프로토콜명>
{
      // 멤버 변수 선언
}

// 프로퍼티 선언
@property 프로퍼티속성 프로퍼티타입 *프로퍼티명;

@end             // 클래스 선언 끝


외부 클래스를 참조할 때는 @class 키워드를 사용합니다.
클래스의 선언은 @class 로 시작하여 @end로 끝납니다.
멤버변수 선언은 { } 안에 합니다.
그리고 그 밑으로 프로퍼티를 선언합니다.

C/C++과는 달리   ObjectvieC에서는 protocall이라는 개념이 있습니다. (네트워크 용어가 아닙니다.)
ObjectiveC에서의 프로토콜은 클래스를 상속받지 않고 메서드를 추가하는 등의 클래스 확장을 하는 것입니다.
물론 프로토콜은 옵션사항입니다.
자세한 개념은 필자도 아직 파악하지 못하고 있습니다. 다음에 기회가 되면 자세히 한 번 다루어 보겠습니다.
그리고 ObjectvieC에서는 property라는 개념을 제공하여 멤버변수에 액세스할 수 있도록 합니다.
프로퍼티 속성으로는 nonatomic, assign | retain | copy, readonly | readwrite 등이 있습니다.
nonatomic을 지정하지 않으면 해당 쓰레드를  lock  한 다음 변수로 부터 값을 꺼냅니다. 그리고 unlock이 됩니다.
nonatomic을 지정하면 lock 절차 없이 바로 값을 반환합니다.
assign | retain | copy 는 프로퍼티로의 대입 방법을 결정합니다. 디폴트는 assign입니다.
assign은 값 자체를 대입합니다.
retain은 이전 오브젝트를 release 하고 새로 들어온 오브젝트를 invoke 합니다.
copy는 이전 오브젝트를 release 하고 새로운 오브젝트를 생성한 다음 새로 들어온 오브젝트를 복사합니다.
readonly를 지정하면 값 반환만 되고 readwrite를 지정하면 반환과 대입 모두 가능합니다. 디폴트는 readwrite입니다.


자 그럼 Application Delegate를 위한 오브젝트가 어떻게 선언되었는지 살펴보겠습니다.


@interface VBAppAppDelegate : NSObject <UIApplicationDelegate> {
    UIWindow *window;
    VBAppViewController *viewController;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet VBAppViewController *viewController;

@end

 

VBAppAppDelegate라는 이름으로 NSObject로 부터 상속받았고 UIApplicationDelegate 프로토콜을 사용하였습니다.
멤버 변수를 2개 선언하고 각각의 멤버변수에 대해 프로퍼터로 선언하였습니다.
그런데 데이터타입 앞에 IBOutlet이라는 키워드가 있습니다. 이것은 Interface Bulder와 연동되었다는 의미입니다.


그리고 다음은 VBAppAppDelegate가 어떻게 정의되었는지 살펴보겠습니다.


#import "VBAppAppDelegate.h"
#import "VBAppViewController.h"

@implementation VBAppAppDelegate

@synthesize window;
@synthesize viewController;

- (void)applicationDidFinishLaunching:(UIApplication *)application {   
   
    // Override point for customization after app launch   
    [window addSubview:viewController.view];
    [window makeKeyAndVisible];
}


- (void)dealloc {
    [viewController release];
    [window release];
    [super dealloc];
}

@end

 

앞서와 마찬가지로 위의 골격으로 ObjectiveC에서 클래스가 어떻게 정의되는지 살펴보겠습니다.


// 클래스 정의 시작
@implementation 클래스명

// 프로퍼티 정의
@synthesize 프로퍼티명;

// 클래스 메서드 정의
+ (리턴타입)메서드명:(파라미터타입)파라미터명
{   
}

// 인스턴스 메서드 정의
- (리턴타입)메서드명:(파라미터타입)파라미터명
{   
}

@end         // 클래스 정의 끝

 

클래스의 정의는 @implementation으로 시작하여 @end로 끝납니다.
헤더파일에서 프로퍼티를 선언했다면 소스파일에서는 프로퍼티를 @synthesize로 정의해야 합니다. 해당 프로퍼티에 대해 setter(대입함수)와 getter(반환함수) 정의 자동화 매크로 정도로 이해하시면 될 듯 합니다. 물론 setter와 getter를 임의로 구현 정의할 수도 있습니다.
다음에 기회가  되면 구체적인 방법을 소개해 보겠습니다.
ObjectiveC에서는 클래스 메서드와 인스턴스 메서드로 구분된다 하였습니다.
클래스 메서드는 플러스기호(+)로 시작하고 인스턴스 메서드는 마이너스기호(-)로 시작합니다.
리턴타입은 괄호로 감싸야 하며 파라미터가 있다면 클론(:)으로 구분해야 합니다.

자 그럼 VBAppAppDelegate 클래스의 정의 내용을 다시 살펴보겠습니다.


@synthesize window;
@synthesize viewController;

 헤더파일에서 선언된 두 개의 프로퍼티를 @synthesize로 정의하였습니다.



- (void)applicationDidFinishLaunching:(UIApplication *)application {   
   
    // Override point for customization after app launch   
    [window addSubview:viewController.view];
    [window makeKeyAndVisible];
}
applicationDidFinishLaunching이라는 인스턴스 메서드가 정의되었습니다. 사실 applicationDidFinishLaunching은 UIApplicationDelegate 프로토콜로 선언된 함수로 iPhone OS 에서 해당 어플리케이션 오브젝트를 생성한 다음 iPhone OS에 의해 실행되도록 설계되었습니다. applicationDidFinishLaunching에서 프로그램의 초기화가 주로 이루어집니다. 여기서는  Window 에 View를 추가하고  해당 윈도우를 메인윈도우로 설정하고 화면에 보여지도록  하고 있습니다.
위 그림에서 알 수 있듯이 UIApplication( )에서 applicatiionDidFinishLaunching을 호출하고 이벤트 루프를 돌다가  어플리케이션 종료가 들어오면 다시 applicationWillTerminate가 호출됨을 알 수 있습니다.


- (void)dealloc {
    [viewController release];
    [window release];
    [super dealloc];
}

dealloc은 NSObject의 인스턴스 메서드 입니다  VBAppAppDelegate 클래스가 NSObject로 부터 상속받았기 때문에 이 메서드를 override하여 정의하고 있습니다. 사용했던 윈도우와 뷰어 컨트롤을 해제하고 상위 클래스의 dealloc을 호출하고 있습니다. 상위 메서드를  호출할 경우 super 를 이용합니다.

 

우선 여기까지 ObjectiveC에 대해 대충 살펴보았습니다.


제목은 초간단 훓어보기인데 내용은 후덜덜이네요 ㅠㅠ


'iOS Programming' 카테고리의 다른 글

UIView의 초기화 루틴 Overriding  (1) 2009.06.01
Xcode Console Debugging  (0) 2009.05.27
Window와 View  (0) 2009.04.20
Hello iPod 2 (레이블과 버튼)  (3) 2009.04.20
Hello iPod  (0) 2009.04.20