如果可能存在保留周期,我通常会使用这样的块:
- (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
运行处理程序时不会被释放?
答案 0 :(得分:4)
在第二个示例中,在特定情况下创建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。它将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
无法释放Request: PUT /products/:productId/coupons
Body:
{
numberOfCoupons: 2
}
}。