根据过渡到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可能会导致保留周期。是否缺少警告意味着不会创建保留周期?为什么警告被认为“可能”导致保留周期?
答案 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 强循环,但它无法确定(通常如上所述无法解析)是否该循环将稍后在不再需要块之前断开,或者创建对象和块是否会形成孤立的循环。因此使用了非确定的“可能”。