是否缺少“可能导致保留周期”的警告意味着不会产生强大的参考周期?

时间:2012-11-12 01:59:51

标签: objective-c xcode llvm block retain-cycle

根据过渡到ARC发行说明,当在块中引用self时,应该使用弱引用以避免强引用/保留周期:

MyViewController *myController = [[MyViewController alloc] init…];
// ...
MyViewController * __weak weakMyController = myController;
myController.completionHandler =  ^(NSInteger result) {
MyViewController *strongMyController = weakMyController;
if (strongMyController) {
    // ...
    [strongMyController dismissViewControllerAnimated:YES completion:nil];
    // ...
}
else {
    // Probably nothing...
}
};

有时候,我会得到一个编译器警告,在块中引用self可能会导致保留周期。是否缺少警告意味着不会创建保留周期?为什么警告被认为“可能”导致保留周期?

1 个答案:

答案 0 :(得分:3)

  

是否缺少警告意味着不会创建保留周期?

没有。编译器能够确定您可以创建保留周期的某些条件,但它不可能排除您创建保留周期的可能性。作为示例,请考虑以下类:

@interface MyClass : NSObject

@property (readwrite, strong) id myObject;

@end

不同的类中的代码片段:

MyClass *one = [MyClass new];
MyClass *two = [MyClass new];

one.myObject = two;
two.myObject = one; // created a strong cycle...

对于编译器甚至发现这个简单的循环需要跨多个类进行流分析,并且通常编译器无法解决此问题(您可以在运行时扫描/发现循环的创建,ARC不会这样做)。

  

为什么警告被认定为“可能”导致保留周期?

创建一个循环本身并没有错或错。如果一个周期成为孤儿,它只是一个问题;即没有实时引用引用它,只有循环引用才能使循环中的对象保持活动状态。

当编译器在正在创建的块中看到对self的强引用时,它知道将创建 live 强循环,但它无法确定(通常如上所述无法解析)是否该循环将稍后在不再需要块之前断开,或者创建对象和块是否会形成孤立的循环。因此使用了非确定的“可能”。