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が言語的にどんどん洗練されてきているのは嬉しいことですね。