从Transitioning to ARC Release Notes为什么我们必须将__block变量设置为零?
使用生命周期预选赛避免强烈参考周期
您可以使用一辈子预选赛避免强烈的参考周期。例如,对于 示例,通常如果您有一个排列在 亲子分层结构中的对象图,并且父母需要引用其子女,并且反之亦然,则可以使父母对子女关系更强壮,并且子对象关系为 - 亲密关系弱。其他情况可能更为微妙,特别是涉及块对象时。
在手动参考计数模式下,
__block id x;
的效果不是 保留x
。在ARC模式下,__block id x;
默认为保留x
(与所有其他值一样,仅为 )。要获得ARC下的手动引用计数模式 行为,可以使用__unsafe_unretained __block id x;
。 因为名称__unsafe_unretained
意味着,但是,具有 非保留变量是危险的(因为它可能会晃动),因此不鼓励 。两个更好的选择是使用__weak
(如果 您不需要支持iOS 4或OS X v10.6),或者将__block
的值设置为nil
以打破保留周期。
好的,那么__block
变量有什么不同?
为什么在这里设置为nil
?是__block
变量保留两次?谁拥有所有的参考?该块?堆?堆栈?线程?什么?
以下代码段使用有时在手动引用计数中使用的模式说明了此问题。
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将不再使用,即块何时到期。
“但块本身也会保留对象,因为它在块内被强引用。”为什么?关闭。 –
添加__block如何产生任何影响? –
当一个块捕获一个指向一个objective-c对象的指针时,除非使用'__weak'或'__unsafe_unretained'(或者非ARC代码中的'__block'),否则该对象将被保留。 –