Objective-C の instancetype キーワードが面白い + typeof(self)の考察

Appleのサンプルコード、iAdSuite を見ていたら見慣れない表現が出てきたので、調べて見ました。

@implementation TextViewController

- (instancetype)init
{
self = [super initWithNibName:@"TextViewController" bundle:nil];
if (self) {
//...
}
return self;
}

こんな感じ、”- (instancetype)init”と書いているのを見て、なんで”-(id) init”じゃないのかなと思いました。

調べてみると、Clang Language Extensions — Clang 3.3 documentation clangのドキュメントによると、

A method with a related result type can be declared by using the type instancetype as its result type. instancetype is a contextual keyword that is only permitted in the result type of an Objective-C method, e.g.

@interface A
+ (instancetype)constructAnA;
@end
The related result type can also be inferred for some methods. To determine whether a method has an inferred related result type, the first word in the camel-case selector (e.g., “init” in “initWithObjects”) is considered, and the method will have a related result type if its return type is compatible with the type of its class and if:

the first word is “alloc” or “new”, and the method is a class method, or
the first word is “autorelease”, “init”, “retain”, or “self”, and the method is an instance method.
If a method with a related result type is overridden by a subclass method, the subclass method must also return a type that is compatible with the subclass type. For example:

@interface NSString : NSObject
– (NSUnrelated *)init; // incorrect usage: NSUnrelated is not NSString or a superclass of NSString
@end
Related result types only affect the type of a message send or property access via the given method. In all other respects, a method with a related result type is treated the same way as method that returns id.

と書いてあり、@interface の中で使うと、指定の型チェックを行うことが出来る機能のようです。つまり、サブクラスの中で戻り値の型を適当に定義したときにエラーが表示されるようになるようです。idの場合は、基本的にどんな型を返してもエラーになりませんが、instancetypeを使うことによって、型チェックの機能をコンパイラで使用することが出来ます。

この instancetype は、Clang 3.0, xcode 4.3 から使用できる機能のようです。ただ、条件として、メソッドの戻り値にしか使用できないという条件があるようで、

__weak instancetype wself = self;

のように書けるのかなと思ったのですが、こちらはエラーになりました。最近は、


__weak typeof(self) wself = self;

と書くようにしています。もちろん、


__weak MyViewController * wself = self;

と書くことも出来るのですが、コピーすると動かなくなったりするので、 typeof(self) を使っています。たしか xcode 4.3 の時は、 typeof(self) は、strong を返していたので、__weak に変換できなかったのですが、xcode 4.4 (clang 3.1) 以降から、__weak typeof(self) が通るようになったようです。blocksを使用するときは、__weakでのselfの参照を頻繁に使用するので、これはうれしい変更ですね。

objective c – Generic typeof for weak self references – Stack Overflow
こちらを見ると、Xcode4.3以前は、

__weak __typeof__((__typeof__(self))self) wself = self;

と書かなくてはいけなかったみたいです。

instancetype から少し脱線しましたが、Objective-Cが言語的にどんどん洗練されてきているのは嬉しいことですね。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください