如果可能存在保留周期,我通常使用这样的 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 不会被释放?
Best Answer-推荐答案 strong>
在第二个示例中,在特定情况下创建 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/
|