如果可能存在保留周期,我通常使用这样的 block :
- (void)someFunction {
__weak __typeof(self) weakSelf = self;
[self setHandler:^{
[weakSelf doSomething];
}];
}
但最近我看到了另一种方式:
- (void)someFunctionWithParamid)param {
__weak __typeof(param) weakParam = param;
[self setHandler:^{
__typeof(weakParam) strongParam = weakParam;
[strongParam doSomething];
}];
}
它们有什么区别?
Edit1:这是否意味着 self
运行处理程序时 param
不会被释放?
在第二个示例中,在特定情况下创建 strongSelf
变量没有任何好处,但我可以向您展示一个有好处的示例。
在第一个示例中,语句 [weakSelf doSomething]
加载 weakSelf
中的引用,保留它,发送 doSomething
消息,然后然后(在 doSomething
返回之后)释放引用。第二个示例“手动”执行基本完全相同的步骤。
这里有一个稍微不同的例子:
- (void)someFunction {
__weak __typeof(self) weakSelf = self;
[self setHandler:^{
[weakSelf doSomething];
[weakSelf doAnotherThing];
}];
}
在我的代码中,假设在调用 block 时只有一个对 self
对象的强引用。 [weakSelf doSomething]
语句创建第二个对它的临时强引用。当 doSomething
运行时,另一个线程释放另一个强引用。当 doSomething
返回时,该语句将释放其临时强引用。现在 self
没有更多的强引用,所以它被释放并且 weakSelf
被设置为 nil。
然后 [weakSelf doAnotherThing]
语句运行。它想加载并保留 weakSelf
的内容,但由于 weakSelf
现在为 nil,该语句只使用 nil。它将 doAnotherThing
消息发送到 nil,这是允许的并且不会崩溃。它什么也不做。它不调用该方法。
这可能不是您想要的行为。如果 doSomething
运行,您可能总是希望 doAnotherThing
在 self
上运行。那是您需要第二个示例中的模式的时候:
- (void)someFunctionWithParamid)param {
__weak __typeof(self) weakSelf = self;
[self setHandler:^{
__typeof(weakSelf) strongSelf = weakSelf;
[strongSelf doSomething];
[strongSelf doAnotherThing];
}];
}
这里,当 block 被调用时,它会立即在 strongSelf
中存储对 self
的强引用(或者如果 weakSelf
有则存储 nil已经设置为零)。 strongSelf
引用直到最后一次使用 strongSelf
变量后才能释放,因此 self
不可能在 之后被释放>doSomething
但在 doAnotherThing
之前。
关于ios - 防止retain-cycle的两种阻塞方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37825148/
欢迎光临 OGeek|极客世界-中国程序员成长平台 (https://ogeek.cn/) | Powered by Discuz! X3.4 |