使用生命周期限定符来避免强引用循环
您可以使用生命周期限定符来避免强引用循环。例如,通常如果您有一个按父子层次结构排列的对象图,并且父母需要引用他们的孩子,反之亦然,那么您可以使父子关系强而子父关系弱. 其他情况可能更微妙,特别是当它们涉及块对象时。
在手动引用计数模式下,
__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
限定符并nil
在完成处理程序中将 myController 变量设置为:
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 将不再被使用,即块何时到期。