Objective c 当同一块被多次执行时,块中的weakSelf和strongSelf会发生什么情况? 前言

Objective c 当同一块被多次执行时,块中的weakSelf和strongSelf会发生什么情况? 前言,objective-c,objective-c-blocks,Objective C,Objective C Blocks,根据“For _弱对象,当前指针对象被保留,然后在当前完整表达式的末尾被释放。”这对我来说表示,如果我这样做: __weak typeof(self) weakSelf = self; [self doSomethingInBackgroundWithBlock:^{ if (weakSelf) { [weakSelf doSomethingInBlock]; } }]; 注 如果您在下面引用@dasblinkenlight的答案,您会注意到在doSomethi

根据“For _弱对象,当前指针对象被保留,然后在当前完整表达式的末尾被释放。”这对我来说表示,如果我这样做:

__weak typeof(self) weakSelf = self;
[self doSomethingInBackgroundWithBlock:^{
    if (weakSelf) {
        [weakSelf doSomethingInBlock];
    }
}];
注 如果您在下面引用@dasblinkenlight的答案,您会注意到在
doSomethingBlock
之前有可能
weakSelf
变成
nil

假设
doSomethingBlock
确实以存在的
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()
(以下)中,self是否可能存在于某些对象中,而不存在于其他对象中

例子 例如,如果我在后台使用类似的方法处理对象数组,其中
processBlock
包含对self的引用:

- (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);
    }
}
这样称呼:

__weak typeof(self) weakSelf = self;
[self processValuesInBackgroundWithArray:someArray usingBlock:^(id object) {
    __strong typeof(weakSelf) strongSelf = weakSelf;
    if (strongSelf) {
        [self doSomethingWithObject:object];
        [self doSomethingElseWithObject:object];
    }      
}];

因此,块引用了
weakSelf
中的
strongSelf
,但该块执行了多次。在数组中对象的迭代之间,
strongSelf
是否有可能变成
nil

无法保证在第一个示例中,
if
中的
weakSelf
将是非
nil
,因为块有两个引用它的完整表达式:

  • if(weakSelf)
    检查是第一个完整表达式
  • [weakSelf doSomethingInBlock]中的
    weakSelf
    调用是第二个
因此,即使只有一个
weakSelf
调用受
if
语句“保护”,也应该应用
strongSelf
的技巧

在processBlock()中,self是否可能存在于某些对象中,而不存在于其他对象中

由于在
processvaluesinbackgrounditharray:
调用中的
过程值之前的堆栈帧中没有保证的
\uu strong
引用,
self
可能在循环的迭代之间被释放,但只有在调用最后一个代码段时,才会对
\uu-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
\u strong
,通过对
myClassObj
的强引用,内部的
self
对象将保留在调用之外,因此无论是否使用
strongSelf
技巧,您的代码都是好的


然而,当
myClassObj
弱时,最后一个
\uu strong
引用与正在运行的循环同时被释放,循环中的一些对象最终会在块中看到
nil
strongSelf
唯一的区别是防止
doSomethingWithObject
nil
上被调用,而
doSomethingWithObject
在非
nil
对象上被调用。

谢谢您的回答!我在问题中添加了关于我的第一个街区的注释。我对最后一部分有点困惑,你有没有可能举一个简短的例子。否则,请给我一分钟时间重读并吸收它,以便我理解它。谢谢@Logan
self
可能存在于块的一次迭代中,然后在该块迭代结束时被解除分配。例如,块中的强引用可能是保持其分配的最后一件事。在这种情况下,弱引用将在下一次迭代开始之前被置零。谢谢@Tommy,这对我来说很有意义!请注意,您不需要在目标C中的if中检查weakSelf-只需在weakSelf上调用方法是安全的。如果weakSelf为nil,则在对其调用方法时不会发生任何事情。这是ObjC的主要原则之一—几乎不需要检查nil。您的工作假设是,如果对象为nil,方法调用就不会执行。对于strongSelf,这是一个风格问题,但惯例是“if(!strongSelf)return;”,而不是将代码放入if块中。无论你想遵循哪一种:“限制化”的观点是在整个区块中保证自己是零或实际值,这比让弱引用在中间某个地方过期的选择要好得多。主要是想从一个执行到另一个执行,这应该会给你答案。自我的生命周期与你对这个对象所做的任何事情都有关系,而不是与这个块有关。它有可能在块中消失,但这只是因为您丢失了对父对象的所有强引用。