そろそろ浸透して話題にも上がらなくなってきた(?)『
iOS 4プログラミングブック』。
補遺その7では、BlocksのObjective-C支援機能に切り込んでみます。
191ページに書いてあるとおり、Objective-Cのオブジェクトは、Block_copy時に自動的にretainされます。
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *string = [NSString stringWithFormat:@"score = %d", score];
void (^block)() = Block_copy(^{
NSLog(@"%@", string);
});
[pool drain];
/* stringはblockからretainされてるから、まだ生きてる */
これどういう仕組みなんでしょう?
Objective-Cのオブジェクトは、みなNSObjectの子供。
NSObjectは、C言語としては、
__attribute__((NSObject))
アトリビュートの付いた変数。
てことで、Block_copy時に__attribute__((NSObject))のついた変数をretainして、Block_release時にreleaseするコードを、コンパイラは簡単に生成できるわけですね。
http://clang.llvm.org/docs/Block-ABI-Apple.txt
2.2.1 Importing __attribute__((NSObject)) variables.
しかし、この自動retainする機能。便利なのはいいのですが、実は気づかないうちに、循環参照してdeallocされない状況に陥ることもある諸刃の剣。
Blockが、Blockをretainしているクラスのselfを自動retainしちゃう、という落とし穴。
詳しくは『
iOS 4プログラミングブック』の193ページに!