ARCリリースノートへの移行から
強力な参照サイクルを回避するために生涯修飾子を使用する
ライフタイム修飾子を使用して、強力な参照サイクルを回避できます。たとえば、通常、親子階層に配置されたオブジェクトのグラフがあり、親が子を参照する必要がある場合、またはその逆の場合は、親と子の関係を強くし、子と親の関係を弱くします。 。他の状況は、特にブロックオブジェクトが関係する場合は、より微妙な場合があります。
手動参照カウントモードで
__block id x;
は、を保持しないという効果がありx
ます。ARCモードでは、__block id x;
デフォルトで保持されますx
(他のすべての値と同様)。ARCでの手動参照カウントモードの動作を取得するには、を使用できます__unsafe_unretained __block id x;
。ただし、名前__unsafe_unretained
が示すように、保持されていない変数を持つことは危険であり(ぶら下がる可能性があるため)、したがって推奨されません。2つのより良いオプションは、使用するか__weak
(iOS4またはOSX v10.6をサポートする必要がない場合)、または保持サイクルを中断するように__block
値を設定することです。nil
さて、__block
変数の違いは何ですか?
なぜnil
ここに設定するのですか?__block
変数は2回保持されますか?誰がすべての参照を保持しますか?ブロック?ヒープ?スタック?スレッド?なに?
次のコードフラグメントは、手動参照カウントで使用されることがあるパターンを使用してこの問題を示しています。
MyViewController *myController = [[MyViewController alloc] init…];
// ...
myController.completionHandler = ^(NSInteger result) {
[myController dismissViewControllerAnimated:YES completion:nil];
};
[self presentViewController:myController animated:YES completion:^{
[myController release];
}];
説明したように、代わりに、修飾子を使用して、完了ハンドラーで__block
myController変数をに設定できます。nil
MyViewController * __block myController = [[MyViewController alloc] init…]; //Why use __block. my controller is not changed at all
// ...
myController.completionHandler = ^(NSInteger result) {
[myController dismissViewControllerAnimated:YES completion:nil];
myController = nil; //Why set to nil here? Is __block variable retained twice? Who hold all the reference? The block? The heap? The stack? The thread? The what?
};
また、なぜコンパイラによってmyController
設定されないのですか。nil
なぜそうしなければならないのですか?コンパイラは、myControllerが再び使用されなくなる時期、つまりブロックが期限切れになる時期をある程度知っているようです。