Objective-C: instancetype 키워드

by Vincent Lee,

Objective-C에서 alloc, init 같은 객체를 할당하고 초기화하는 메소드들은 제네릭 타입인 id 형을 리턴 형으로 하는 규칙(convention)을 사용한다.

@interface NSObject
+ (id)alloc;
- (id)init;
@end

여기서 제네릭 타입을 리턴 형으로 사용하니 생성된 객체를 다른 형(type)에 대입하거나, 초기화 과정에서 잘못된 메소드의 호출을 컴파일 시에 미리 발견할 수 없다는 문제가 생긴다.

// No errors at compile time.
NSArray *array = [[NSDictionary alloc] init];
NSArray *array = [[[NSArray alloc] init] undefinedMethod];

또한, Xcode와 같은 IDE 툴의 자동 완성 기능이 형을 추론하기 힘들어 편집 시에 적절한 메소드를 제안하기 어렵다는 점도 있다. 이런 점들을 보완하고 형 안정성(type safety)을 향상하기 위해 instancetype 키워드가 추가되었다.

Objective-C에서 특정한 이름(alloc, init 등)을 가진 메소드는 항상 그 객체의 형을 가진 인스턴스를 리턴하는데, 이것을 “연관된 리턴 형(related result type)을 가진다”고 말한다. 예를 들어,

NSArray *array = [NSArray alloc];

여기서 alloc 메소드의 리턴 형은 id 형이지만 이 메소드는 암묵적으로 연관된 리턴 형을 가지고 있으므로, 실제로 할당되어 리턴된 객체는 NSArray * 형이다.

연관된 리턴 형을 가진 메소드는 컴파일러(Clang)에 의해 추론될 수 있는데, 다음의 조건을 가지는 메소드의 리턴 형(id)은 컴파일 시에 instancetype으로 승격(promotion)되어 형 안정성을 높인다.

  • 첫 단어가 alloc 또는 new로 시작하는 클래스 메소드이거나
  • 첫 단어가 autorelease 또는 init, retain, self로 시작하는 인스턴스 메소드

이 조건에 해당하지 않는 메소드를 만들 때에는 리턴 형을 명시적으로 instancetype 형으로 선언해야 한다.

참고로, OS X 10.10(Yosemite)와 iOS 8 SDK부터 위 조건에 해당하는 리턴 형 id는 모두 명시적으로 instancetype 형으로 선언된다.

References

1 Adopting Modern Objective-C (iOS Developer Library)

2 Related result types (Clang Language Extensions)