如果可能存在保留周期,我通常使用这样的块:
- (void)someFunction {
__weak __typeof(self) weakSelf = self;
[self setHandler:^{
[weakSelf doSomething];
}];
}
但是最近我看到了另一种方式:
- (void)someFunctionWithParam:(id)param {
__weak __typeof(param) weakParam = param;
[self setHandler:^{
__typeof(weakParam) strongParam = weakParam;
[strongParam doSomething];
}];
}
它们之间有什么区别?
Edit1:这是否意味着在运行处理程序的
param
时不会释放self
? 最佳答案
在第二个示例中,在这种特定情况下创建strongSelf
变量没有任何好处,但是我可以向您展示一个有好处的示例。
在第一个示例中,语句[weakSelf doSomething]
将引用加载到weakSelf
中,保留该引用,发送doSomething
消息,然后(在doSomething
返回之后)释放该引用。第二个示例“手动”执行了完全相同的步骤。
这是一个稍微不同的示例:
- (void)someFunction {
__weak __typeof(self) weakSelf = self;
[self setHandler:^{
[weakSelf doSomething];
[weakSelf doAnotherThing];
}];
}
在我的代码中,假设在调用该块时只有一个对
self
对象的强引用。 [weakSelf doSomething]
语句创建第二个临时强引用。当doSomething
运行时,另一个线程释放另一个强引用。当doSomething
返回时,该语句释放其临时强引用。现在self
不再具有更强的引用,因此将其释放,并将weakSelf
设置为nil。然后
[weakSelf doAnotherThing]
语句运行。它想加载和保留weakSelf
的内容,但是由于weakSelf
现在为nil,因此该语句仅使用nil。它将doAnotherThing
消息发送到nil,这是允许的,并且不会崩溃。它什么也没做。它不调用方法。这可能不是您想要的行为。也许您总是,如果
doAnotherThing
运行,则希望self
在doSomething
上运行。那是您在第二个示例中需要该模式时:- (void)someFunctionWithParam:(id)param {
__weak __typeof(self) weakSelf = self;
[self setHandler:^{
__typeof(weakSelf) strongSelf = weakSelf;
[strongSelf doSomething];
[strongSelf doAnotherThing];
}];
}
在这里,当调用该块时,它立即在
self
中存储对strongSelf
的强引用(或者,如果weakSelf
已经设置为nil,则存储nil)。直到最后一次使用strongSelf
变量后,才能释放strongSelf
参考,因此,不可能将self
释放在doSomething
之后但在doAnotherThing
之前。关于ios - 防止滞留周期的两种挡块方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37825148/