9

ブロックivarに見かけの参照サイクルを持つコードがあります。次のコードは、基準周期を引き起こし、にdeallocが呼び出されることはありません:__block ARCのivarブロックの自己参照サイクル

__block MyViewController *blockSelf = self; 

loggedInCallback = ^(BOOL success, NSError *error){ 
    if (success) 
    { 
     double delayInSeconds = 1.0; 
     dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
     dispatch_after(popTime, dispatch_get_main_queue(), ^(void) 
     { 
      [blockSelf.delegate loginDidFinish]; 
     });    
    } 
}; 

しかし、私はキャプチャするブロックのスコープのための私のデリゲートへの参照を保持するために、別の__block変数を作成した場合、基準サイクルが消える:

__block id <MyViewControllerDelegate> blockDelegate = self.delegate; 

loggedInCallback = ^(BOOL success, NSError *error){ 
    if (success) 
    { 
     double delayInSeconds = 1.0; 
     dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
     dispatch_after(popTime, dispatch_get_main_queue(), ^(void) 
     { 
      [blockDelegate loginDidFinish]; 
     });    
    } 
}; 

ここで何が起こっているのかを知りたいだけです。

答えて

16

私はここでARCを使用していると仮定します。 ARCの前に、あなたの最初の例はうまくいくでしょう。 ARCでは、__blockのセマンティクスが変更されました。 __block宣言は弱くではなく強くキャプチャされるようになりました。最初のサンプルで__block__weakと交換し、すべてが正常に動作するはずです。

2番目の例の動作については、デリゲートへの強力な参照を作成していますが、そのオブジェクトには参照が戻っていません。したがって、サイクルや誰もが幸せではありません。

私は、特にブロックキャプチャと__weakhttp://www.mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html

+0

パーフェクトまわり、ARCで導入された変更のマイク・アッシュの記事を読んで感謝をお勧めします!質問のタイトルをよりわかりやすいように更新しました。 –

+1

私はiOS 4.3をターゲットにしているので、代わりに '' __unsafe_unretained''を使用しなければなりませんでしたが、うまくいきました! –