RSS

Tag Archives: cocoa

Objective-C 배우기 : 입문서

Objective-C 배우기 : 입문서

Objective-C는 세련된 객체지향 프로그래밍이 가능하게 설계된 컴퓨터 프로그래밍 언어입니다. Objective-C는 클래스와 함수 선언, 클래스의 동적 확장을 위한 문법을 제공하기 위해서 standard ANSI C 언어를 확장한 것입니다.

중요 : 이 문서는 C언어의 어떤 측면을 가르키기 위한 것이 아닙니다. C언어가 친숙하지 않으시다면, C의 기본부터 공부해야합니다. 또한 객체지향 프로그래밍의 기본적인 개념부터 공부하셔야 합니다. 객체의 사용과 객체지향 디자인 패턴은 코코아 어플리케이션의 디자인을 토대로합니다. 그리고 이것이 어떻게 상호작용하는지 이해하는 것은 어플리케이션을 만드는것과 매우 관련 깊습니다. 이 개념의 개요를 더 보고 싶으시다면, 객체지향 프로그래밍과 Objective-C을 읽보십시오. 그리고 코코아에 사용되는 디자인 패턴을 위해서 코코아 기초 가이드를 읽어보십시오.

C언어와 친숙하거나 객체지향으로 프로그래밍을 해본 경헙이 있다면, 아래 내용은 Objective-C의 기본 문법을 익히는데 도움을 줄것입니다. 캡슐화, 상속, 다형성과 같은 전통적인 객체지향 개념의 많은 부분이 Objective-C에서 사용됩니다. 다른점이 조금 있긴 하지만, 이 글에서 다른점들을 볼 수 있고 더 자세한 내용도 찾아 보실 수 있을 것입니다.

Objective-C의 자세한 내용과 문법을 위해서, Objective-C 프로그래밍 언어를 읽어 보시기 바랍니다.

내용:

—————————————————————————————————————————————————-

Objective-C : C의 상위 집합

Objective-C는 C언어 ANSI버전의 상위 집합이고 C의 기본문법을 지원합니다. C코드와 마찬가지로, 구현한 코드에서 공개시키기 위한 선언부를 분리 시키기 위해 헤더파일과 소스파일을 정의 할 수 있습니다. Objective-C의 헤더파일은 Table 1-1 과 같은 확장자를 사용합니다.

Table 1-1. Objective-C의 확장자

확장자 소스 타입
.h 헤더 파일. 헤더 파일은 클래스, 타입, 함수, 상수 선언들을 포함합니다.
.m 소스 파일. Objective-C와 C의 소스 코드를 포함하는 파일의 전형적으로 쓰이는 확장자 입니다.
.mm 소스 파일. 이 확장자로 된 소스 파일은 Objective-C와 C를 포함하여 C++코드를 포함합니다. C++코드를 참조를 하거나 Objective-C으로 부터 다른 특징을 가진다면 이 확장자를 사용하셔야합니다.

당신의 소스코드에 헤더파일을 포함하고 싶다면, 전형적으로 #import를 바로 사용합니다. 이것은 같은 파일을 한번이상 포함 하지 않게 확인해주는 기능 이외에 #include와 같습니다. Objective-C 샘플 코드와 문서 그리고 당신의 코드 또한 #import를 사용 할 것입니다.

—————————————————————————————————————————————————-

클래스

대부분의 다른 객체지향 언어와 같이, Objective-C의 클래스는 데이터와 그 데이터를 운영하기 위한 행동들을 캡슐화하기 위한 기본 구조 제공합니다. 객체는 클래스의 실행 중 생성되는(런타임) 인스턴스이고 메모리상에서 클래스에 의해 선언된 변수들과 메소드으로의 포인터들의 복사본을 가집니다.

Objective-C에서 클래스 명세는 명백한 두 부분(구현부와 선언부)으로 구성되어집니다. 선언부에서는 클래스 선언, 인스턴스 변수, 클래스와 관련된 메소드들을 포함합니다. 선언부는 주로 .h파일에 작성합니다. 구현부에서는 클래스의 메소드를 위한 실직적 코드를 포함합니다. 구현부는 주로 .m파일에 작성합니다.

Figure 1-1은 코코아의 기본 클래스인 NSObject의 상속을 받은 MyClass라는 클래스를 정의하는 문법을 보여줍니다. 클래스 정의는 컴파일러에게 알려주기위해 @interface로 시작해서 @end로 끝납니다. 콜론(:)으로 분리되어있는 다음 클래스 이름은 부모 클래스의 이름입니다. 클래스의 인스턴스 변수는 중괄호( { 와 } )로 감싸서 작성합니다. 다음엔 메소드에 의해 선언된 메소드들의 리스트가 있습니다. 모든 인스턴스 변수와 메소드 선언끝에는 세미콘론(;)으로 표시합니다.

Figure 1-1 클래스 선언

알림 : 클래스는 프로퍼티를 선언 할 수 있지만, 이 선언부는 메소드만 선언되어 있습니다. 프로퍼티에 대한 더 많은 정보를 위해서는 프로퍼티 선언을 읽어 보시길 바랍니다.

Objective-C는 객체를 포함하는 변수를 위해 강한 타이핑(strong typing)과 약한 타이핑(weak typing)을 모두 지원합니다. 강한 타입 변수는 변수 타입 선언에서 클래스 이름을 가집니다. 약한 타입 변수는 클래스 이름 대신에 id라는 이름을 사용합니다. 약한 타입 변수는 주로 정확한 타입을 알수 없는 객체를 가진 콜랙션과 같은 것들을 위해 사용됩니다. 강한 타입을 사용하는 언어를 사용해왔다면, 약한 타입 변수를 사용하는것은 문제를 만들 수 있다는 것을 고려하셔야 합니다. 그러나 실직적으로 약한 변수 타입의 사용은 Objective-C의 동적 프로그래밍에서 엄청난 유동성을 제공합니다.

아래 예제는 강한 타입과 약한 타입 변수 선언을 보여줍니다.

MyClass *myObject1; // Strong typing
id myObject2; // Weak typing

첫 번째 선언에 있는 *을 주의하세요. Objective-C에서의 객체 참조는 포인터입니다. 이 내용이 확실히 이해가 가지 않더라도 걱정 안 하셔도 됩니다. Objective-C로 프로그래밍 하기 위해서는 포인터를 전문가처럼 사용할 필요는 없습니다. 강한 타입 변수를 선언하기 위해서는 변수 이름 앞에 *을 써야한다는 것만 잊지 마세요. id 타입은 포인터를 나타냅니다.
—————————————————————————————————————————————————-

메소드와 메세징

Objective-C에서 메소드는 두 가지의 타입(instance method와 class method)으로 선언할 수 있습니다. 인스턴스 메소드는 클래스의 특정 인스턴스에 의해 실행됩니다. 다시 말하면, 인스턴스 메소드를 부르기전에는 먼저 클래스의 인스턴스를 만들어야합니다. 반면에 클래스 메소드는 인스턴스를 만들 필요가 없습니다. 나중에 더 상세히 다룰 것입니다.

함수의 선언은 메소드 타입 식별자, 리턴 타입, 하나 이상의 시그네처 키워드(메소드의 이름이라 생각하시면 됩니다.), 파라미터 타입과 이름으로 구성되어 있습니다. Figure 1-2는 insertObject:atIndex:인스턴스 메소드의 선언을 보여줍니다.

Figure 1-2. 메소드 선언 문법

method declaration syntax

마이너스(-)로 시작하는 이 선언 인스턴스 메소드임을 지시합니다. 이 메소드의 이름(insertObject:atIndex:)은 시그네처 키워드와 콜론(:)을 붙여서 부름니다. 콜론(:)은 파라미터가 있다는 것을 명시합니다. 메소드에 파라미터가 없다면, 콜론을 빼고 시그네처 키워드만을 써야합니다. 이 예제에서는 파라미터가 두개 있다는 것을 의미합니다.

객체에게 메세지를 보냄으로써 메소드를 호출 할 수 있습니다. 메세지는 메소가 필요한 파라미터를 가진 시그네처 키워드입니다. 객체에 보내진 모든 메세지는 동적으로 보내져서 Objective-C 클래스의 다형성을 가능하게 해줍니다.

메세지는 대괄호( [ 와 ] )로 감싸집니다. 대괄호 안에서 메세지를 받는 객체는 왼쪽에 메세지(메세지가 필요한 파라미터와 함께)는 오른쪽에 적습니다. 예를 들어 myArray 변수 안에 있는 객체에게 insertObject:atIndex:메세지를 보내기 위해서는 아래와 같은 문법을 사용합니다.

[myArray insertObject:anObject atIndex:0];

결과를 임시로 저장하기 위해서 선언하는 수많은 지역변수를 줄이기 위해서, Objective-C는 메세지를 중첩해서 사용 할 수 있게 해줍니다. 끼워 넣어진 메소드의 리턴값은 파미터로 사용되거나 다른 메세지의 타겟으로 사용됩니다. 예를 들어, 위 예제에서 당신은 어떤 변수를 다른 메세지의 결과 값으로 대체하고 싶다고 생각합니다. 만일 어떤 배열과 배열에 넣을 객체에 접근 할 수 있는 메소드를 가지고있는 myAppObject라는 객체를 있다면, 아래와 같이 작성할 수 있습니다.

[[myAppObject theArray] insertObject:[myAppObject ObjectToInsert] atIndex:0];

또한 Objective-C는 접근자 메소드를 부르기위해 점(.) 문법을 제공합니다. 접근자 메소드는 변수의 상태를 얻거(get)나 지정(set)할 수 있습니다. 일반적으로 -(type)propertyName-(void)setPropertyName:(type)과 같은 형식을 취합니다. 점(.) 문법을 사용하여 위 예제를 아래와 같이 바꿀 수 있습니다.

[myAppObject.theArray insertObject:[myAppObject ObjectToInsert] atIndex:0];

또한 대입을 위해 점(.) 문법을 사용할 수 있습니다.

myAppObject.theArray = aNewArray;

이 것은 단순히 [myAppObject setTheArray:aNewArray];의 다른 모양일뿐입니다.

앞의 예제는 클래스의 인스턴스에 메세지를 보내는것이지만, 클래스 자체에도 메세지를 보낼 수 있습니다. 클래스에게 메세지를 보내기 위해서는 명세된 메소드는 인스턴스 메소드(-) 대신에 클래스 메소드(+)로 정의 되어 있어야 합니다.

일반적으로 클래스 메소드는 인스턴스를 생성하기위한 메소드(factory method)로 사용하거나 클래스와 관련된 정보에 접근하기 위해 사용됩니다. 클래스 메소드를 선언하기 위한 문법은 메소드 타입 식별자를 마이너스(-)대신 플러스(+)를 사용하는 것 이외에는 동일합니다.

다음 예제는 클래스 메소드를 인스턴스를 생성하기위한 메소드로써 어떻게 사용되는지를 보여줍니다. 여기서 array는 NSArray의 클래스 메소드 입니다. 이 메소드는 NSMutableArray에 상속되었고, 새로운 인스턴스를 생성하고 초기화 합니다.



NSMutableArray *myArray = nil;  // nil은 근본적으로 NULL과 같습니다.// 새로운 배열을 만들어서 myArray라는 변수에 대입합니다.
myArray = [NSMutableArray array];

Listing 1-1은 이전 예제로 부터 myClass의 구현부를 보여줍니다. 클래스를 선언 하는것과 마찬가지로 @implementation@end를 사용하여 컴파일러에게 알려줍니다. 이 지시어들은 컴파일러가 해당 클래스에 선언된 메소드의 정보를 찾기위해 제공됩니다. 클래스의 정의는 선언부안에 있는 해당 메소드를 매칭시킵니다.

Listing 1-1 클래스 구현

@implementation MyClass– (id)initWithString:(NSString *)aName

{

self = [super init];

if (self) {

name = [aName copy];

}

return self;

}

+ (MyClass *)createMyClassWithString: (NSString *)aName

{

return [[[self alloc] initWithString:aName] autorelease];

}

@end

—————————————————————————————————————————————————-

프로퍼티 선언

프로퍼티 선언은 접근자 메소드의 선언과 구현을 위한 편리한 표현법입니다.

프로퍼티 선언은 클래스의 선언부에 넣어야합니다. 기본 정의는 @property를 사용해 컴파일러에게 알려줍니다. 이어서 타입과 프로퍼티 이름을 적어줍니다. 또한 접근자 메소드가 어떻게 행동하는지를 정의하기위해 옵션을 사용하여 프로퍼티를 설정할 수 있습니다. 아래 예제는 프로퍼티를 선언하기 위한 간단한 예제를 보여줍니다.

@property BOOL flag;@property (copy) NSString *nameObject; // 대입할때 객체를 복사합니다.

@property (readonly) UIView *rootView; // 게터 메소드(getter method)만 선언 합니다.

읽을 수 있는(readable) 프로퍼티는 프로퍼티의 이름(propertyName)과 똑같은 메소드를 명세합니다. 쓸 수 있는(writable) 프로퍼티는 추가로 프로퍼티의 이름의 첫자를 대문자로 바꾼 setPropertyName:메소드를 명세합니다. (역자주 : 여기서 명세(specify)한다는 말은 선언만 한 것이지 구현이 된것은 아님을 뜻합니다.) 

클래스의 구현부에서 @synthesize를 사용해 컴파일러에게 선언부에서의 명세에 따른 메소드 생성을 요청할 수 있습니다.

@synthesize flag; @synthesize nameObject;

@synthesize rootView;

원한다면 @synthesize 문장을 한줄로 합칠 수도 있습니다.

@synthesize flag, nameObject, rootView;

실제로 프로퍼티는 작성해야할 많은 코드를 줄려줍니다. 대부분의 접근자 메소드가 이와 같은 방법으로 구현되기 때문에, 클래스에서 노출되는 프로퍼티의 게터와 세터 메소드를 구현해야하는 많은 노력을 줄여줍니다. 프로퍼티 선언과 신더사이즈를 사용하여 컴파일 시간에 원하는 행동들을 명세할 수 있습니다.

당신에게 맞는 프로퍼티 선언에 대해 더 많은 정보를 얻고 싶다면, Objective-C 프로그래밍 언어 안에 있는 “프로퍼티 선언”을 읽어보시기 바랍니다.

—————————————————————————————————————————————————-

문자열

Objective-C는 C의 상위 집합이기 때문에, 문자열을 명세하기위해서 C 와 같은 관습을 제공합니다. 따라서, 문자 하나는 따옴표( ‘ 와 ‘ )로, 문자열은 쌍따옴표( ” 와 ” )로 감쌉니다. 그러나 Objective-C 프레임워크에서는 일반적으로 C-스타일의 문자열을 사용하는것 대신에 NSString 객체를 주고 받습니다.

NSString 클래스는 유동적인 길이를 가진 문자열의 저장을 위해 자체 메모리 관리, 유니코드 지원, printf-스타일 형식 기능와 같은 필요한 장점을 모두 가진 문자열을 위한 객체를 제공합니다. 일반적으로 문자열은 전역에서 많이 사용되기 때문에, Objective-C는 상수값을 가진 NSString 객체를 만들기위해서 간단한 표기법을 제공합니다. 아래 예제와 같이, 일반적으로 사용하는 쌍따옴표 문자열 앞에 @ 기호를 같이 써주시면 됩니다.

NSString *myString = @”My String\n”;
NSString *anotherString = [NSString stringWithFormat:@”%d %@”, 1, @”String”];
// C문자열로 Objective-C 문자열을 만듭니다.
NSString *fromCString = [NSString stringWithCString:”A C string” encoding:NSASCIIStringEncoding];

—————————————————————————————————————————————————-

프로토콜

프로토콜은 어떤 클래스에 의해 구현될 수 있는 메소드를 선언합니다. 프로토콜은 그들 스스로 클래스가 아닙니다. 그들은 간단히 다른 객체가 구현하여 응답할 수 있는 인터페이스를 정의합니다. 클래스 중 한군데서 프로토콜의 메소드를 구현 할 때, 클래스는 그 프로토콜을 따라야한다고 말합니다.

프로토콜은 주로 델리게이트 객체를 위한 인터페이스 명세를 위해 사용됩니다. 프로토콜과 델리게이트, 따른 객체간은 상호작용을 보는 가장 좋은 방법은 예제를 보는 것입니다.

UIApplication 클래스는 어플리케이션의 요청된 행동을 구현합니다. 어플리케이션의 현재 상태에 대한 간단한 알림을 얻기위해 UIApplication을 서브클래싱 하는것 대신에, UIApplication은 지정된 델리게이트 객체의 명세된 메소드들을 호출함으로써 알림들을 배달합니다. UIApplicationDelegate 프로토콜의 메소드를 구현한 객체는 알림을 받을 수 있고, 적절한 응답을 제공해 줄 수 있습니다. 클래스 이름 뒤에 “<>”안에 프로토콜의 이름을 써넣음으로써 상속한 클래스가 프로토콜을 따르거나 채택한다는 것을 명세합니다.

@interface MyClass : NSObject <UIApplicationDelegate, AnotherProtocol>{
}
@end

프로토콜의 선언은 부모 클래스를 가지고 있지 않다는 것과 인스턴스 변수를 정의하지 않는다는것을 제외하면 클래스 선언와 유사하게 보입니다. 아래 예제는 하나의 메소드를 선언한 간단한 프로토콜의 선언을 보여줍니다.

@protocol MyProtocol
– (void)myProtocolMethod;
@end

많은 델리게이트 프로토콜의 경우에는, 프로토콜을 채택하는 것은 단순히 그 프로토콜에 의해 정의된 메소드를 구현한다는 것입니다. 당신이 프로토콜을 지원하다는 것을 명백하게 언급하도록 요구하는 프로토콜이 있습니다. 그리고 프로토콜은 필수와 선택 메소드를 명세할 수 있습니다. 하지만, 더 낫은 개발을 위해서는 Objective-C 프로그래밍 언어안의 “프로토콜”을 읽음으로써, 프로토콜과 그들이 어떻게 사용되는지에 대해서 배우는데 약간 더 많은 시간을 보내셔야합니다.
—————————————————————————————————————————————————-

더 배우기

지금까지의 글은 단지 Objective-C언어의 기본에 친근해지기 위해 쓰여졌습니다. 여기서 다룬 내용은 이 문서의 전체에서 마주칠 수 있는 거의 대부분의 언어의 특징을 반영합니다. 이 글은 언어의 특징들 뿐만 아니라 Objective-C 프로그래밍 언어 안에 있는 내용을 읽어 볼 수 있게 도와주는 역활을 합니다.

—————————————————————————————————————————————————-

원문 : Learning Objective-C

 
Leave a comment

Posted by on August 17, 2011 in iOS Developer Library 번역

 

Tags: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,