根据Clang docs,“对于__weak对象,当前的指针被保留,然后在当前的完整表达式结束时释放。”对我来说这表明如果我这样做:
__weak typeof(self) weakSelf = self;
[self doSomethingInBackgroundWithBlock:^{
if (weakSelf) {
[weakSelf doSomethingInBlock];
}
}];
注意
如果你在下面提到@dasblinkenlight的答案,你会注意到weakSelf
之前nil
可能会变成doSomethingBlock
。
假设doSomethingInBlock
确实以weakSelf
存在,其余部分应该没有问题,并且weakSelf
在执行完成之前不会有nil
成为__weak typeof(self) weakSelf = self;
[self doSomethingInBackgroundWithBlock:^{
if (weakSelf) {
// Guaranteed to be retained for scope of expression
[weakSelf doSomethingInBlock];
// weakSelf could possibly be nil before reaching this point
[weakSelf doSomethingElseInBlock];
}
}];
的风险。但是,如果我要这样做:
weakSelf
建议使用__weak typeof(self) weakSelf = self;
[self doSomethingInBackgroundWithBlock:^{
__strong typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf doSomethingInBlock];
[strongSelf doSomethingElseInBlock];
}
}];
并将其转换为块内的强变量,如下所示:
weakSelf
在同一个块的多次迭代中,strongSelf
和processBlock()
会发生什么?是否有可能在processBlock
(下图)中,某些物体可能存在自我而不存在其他物体?
例如,如果我使用类似的东西在后台处理一个对象数组,那么- (void) processValuesInBackgroundWithArray:(NSArray *)array usingBlock:(void (^)(id))processBlock {
for (id ob in array) {
// Block is called for each Object
// Is there a chance that self will exist for some objects and not for others?
processBlock(ob);
}
}
包含对self的引用:
__weak typeof(self) weakSelf = self;
[self processValuesInBackgroundWithArray:someArray usingBlock:^(id object) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
[self doSomethingWithObject:object];
[self doSomethingElseWithObject:object];
}
}];
这样称呼:
strongSelf
因此该块引用weakSelf
中的strongSelf
,但该块被多次执行。在数组中的对象迭代之间,nil
是否有可能变为{{1}}?
答案 0 :(得分:3)
我们无法保证在您的第一个示例中weakSelf
内的if
为非nil
,因为该块有两个引用它的完整表达式:
if (weakSelf)
检查是第一个完整表达式weakSelf
调用[weakSelf doSomethingInBlock];
是第二个。因此,即使只有一个strongSelf
调用"受保护",也应该应用weakSelf
的技巧。通过if
声明。
是否有可能在processBlock()(下面)中,self可能存在于某些对象而不存在于其他对象中?
由于__strong
调用之前的堆栈帧中没有保证processValuesInBackgroundWithArray:
引用,self
可能会在循环的迭代之间释放,但仅限于调用您的上一个代码段发生在__weak
或对包含上一个代码段中方法的对象的未经许可的引用。
我们假设您的最后一个代码段位于一个名为testWeak
的方法中,位于名为MyClass
的类中:
-(void)testWeak {
__weak typeof(self) weakSelf = self;
[self processValuesInBackgroundWithArray:someArray usingBlock:^(id object) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
[self doSomethingWithObject:object];
[self doSomethingElseWithObject:object];
}
}];
}
当这样的呼叫发生时
[myClassObj testWeak];
且myClassObj
为__strong
,self
内的testWeak
对象将通过强引用myClassObj
保留在调用之外,因此您的代码将会无论有没有strongSelf
技巧,都要好。
但是当myClassObj
较弱时,最后一个__strong
引用会与正在运行的循环同时释放,循环中的某些对象最终会看到nil
{{1}在块内。 weakSelf
将要做的唯一区别是阻止strongSelf
上doSomethingElseWithObject
会被调用,而nil
将会调用非doSomethingWithObject
对象