【发布时间】:2012-06-15 10:09:28
【问题描述】:
来自Transitioning to ARC Release Notes
使用生命周期限定符来避免强引用循环
您可以使用生命周期限定符来避免强引用循环。为了 例如,通常如果您有一个以 父子层次结构和父母需要参考他们的孩子和 反之亦然,那么您就可以使父母与孩子的关系变得牢固,并且 亲子关系薄弱。其他情况可能更多 微妙的,尤其是当它们涉及块对象时。
在手动引用计数模式下,
__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 将不再被使用,即块何时过期。
【问题讨论】:
标签: objective-c xcode4.3