在执行期间将块设置为nil时会发生什么?

Aar*_*ron 5 objective-c objective-c-blocks automatic-ref-counting

假设我有一个对块有强引用的对象.在执行该块的某个时间,强引用设置为nil.块是否保证完成执行,或者这会导致崩溃?我已经看到了exc-bad-access错误,但是我无法可靠地生成它们,所以我不知道它们为什么会弹出.

例如:

-(void)method
{
    self.block = ^{
        //code
        self.block = nil;
        //more code - crash here?
    }
}

-(void)otherMethod
{
    block();
}
Run Code Online (Sandbox Code Playgroud)

Aar*_*ron 3

我相信这个问题我终于有了满意的答案。请注意,这都是在 ARC 的上下文中。

块在执行期间可能会被释放。该块将继续正常执行,但其任何指向捕获变量的指针都会变得可疑(并且有潜在危险)。

假设ObjectA有一个名为completion的块复制属性:

@property (nonatomic, copy) void (^completion)();
Run Code Online (Sandbox Code Playgroud)

...作业看起来像这样:

__weak ObjectA * weakSelf = self;
self.completion = ^{
    weakSelf.completion = nil;
    [weakSelf doSomethingElse];
};
Run Code Online (Sandbox Code Playgroud)

如果像这样调用该块......

-(void)method
{
    _completion(); //directly uses ObjectA's instance of the block
}
Run Code Online (Sandbox Code Playgroud)

...然后,假设没有其他东西引用该块的该实例,它就会被释放,并且其捕获的变量weakSelf 变为nil。doSomethingElse 从未被调用。解决这个问题的最佳方法是简单地使用其访问器调用该块 - 这将在堆栈上分配一个新副本。原始副本将被释放,但新副本及其所有捕获的变量将在当前上下文中保留下来。

-(void)method
{
    self.completion(); //uses new copy of the block
}
Run Code Online (Sandbox Code Playgroud)