ブロックのドキュメントから:
参照カウント環境では、ブロック内で Objective-C オブジェクトを参照すると、デフォルトで保持されます。これは、オブジェクトのインスタンス変数を参照するだけの場合でも当てはまります。
作業が実行される前にブロックがオブジェクトに与えられ、作業が実行された後にブロックがレシーバーによって実行される完了ハンドラーパターンを実装しようとしています。私は良いメモリ市民であるため、ブロックは完了ハンドラーで参照するオブジェクトを所有する必要があり、ブロックがスコープ外になると解放されます。copy
ブロックは、それが宣言されたスタック スコープを通過しても存続するため、ブロックをヒープに移動する必要があることは十分にわかっています。
ただし、オブジェクトの 1 つが予期せず割り当て解除されています。いくつか遊んだ後、ブロックがヒープにコピーされたときに特定のオブジェクトが保持されていないように見えますが、他のオブジェクトは保持されています。何が間違っているのかわかりません。私が作成できる最小のテストケースは次のとおりです。
typedef void (^ActionBlock)(UIView*);
いくつかのメソッドの範囲内:
NSObject *o = [[[NSObject alloc] init] autorelease];
mailViewController = [[[MFMailComposeViewController alloc] init] autorelease];
NSLog(@"o's retain count is %d",[o retainCount]);
NSLog(@"mailViewController's retain count is %d",[mailViewController retainCount]);
ActionBlock myBlock = ^(UIView *view) {
[mailViewController setCcRecipients:[NSArray arrayWithObjects:@"test@recipient.com",nil]];
[o class];
};
NSLog(@"mailViewController's retain count after the block is %d",[mailViewController retainCount]);
NSLog(@"o's retain count after the block is %d",[o retainCount]);
Block_copy(myBlock);
NSLog(@"o's retain count after the copy is %d",[o retainCount]);
NSLog(@"mailViewController's retain count after the copy is %d",[mailViewController retainCount]);
ある時点で両方のオブジェクトがブロックによって保持されることを期待しており、それらの保持カウントが同じであることは確かです。代わりに、次の出力が得られます。
o's retain count is 1
mailViewController's retain count is 1
mailViewController's retain count after the block is 1
o's retain count after the block is 1
o's retain count after the copy is 2
mailViewController's retain count after the copy is 1
o
( のサブクラスNSObject
) は適切に保持されており、範囲外にはなりません。ただしmailViewController
、保持されず、ブロックが実行される前に割り当てが解除されるため、クラッシュが発生します。