块中的弱自我

Era*_*lpB 2 weak-references objective-c weak-ptr ios

我是否需要检查弱自我是否在块中为零?

我创建了weakSelf指针,如:

__weak typeof(self) weakSelf = self;
Run Code Online (Sandbox Code Playgroud)

在我做的块的开头

if(!weakSelf){return;}
Run Code Online (Sandbox Code Playgroud)

这是不必要的吗?或者它取决于我是否正确编码其余部分,以便当自我死亡时,其他人也会死亡?

rob*_*off 11

这种检查是不必要的,并且给你一种错误的安全感.

这是问题所在:

__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
    if (!weakSelf) { return; }
    // THE LINE OF INTEREST
    [weakSelf doSomething];
});
Run Code Online (Sandbox Code Playgroud)

THE LINE OF INTEREST某些其他线程可能会清除最后一个强引用self,此时weakSelf设置为nil.所以doSomething消息被发送到nil,这是"安全的"(它什么都不做),但可能不是你所期望的!

如果你想在weakSelfnil 时采取不同的行动,那就更糟了,例如

__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
    if (weakSelf) {
        [weakSelf doSomething];
    } else {
        [someOtherObject doSomethingElse];
    }
});
Run Code Online (Sandbox Code Playgroud)

在这种情况下,在块验证weakSelf不是nil的时间和它发送doSomething消息的时间之间,weakSelf可能变为nil,既doSomething不会也doSomethingElse不会实际运行.

正确的解决方案是:

__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
    typeof(self) strongSelf = weakSelf;
    if (strongSelf) {
        [strongSelf doSomething];
    } else {
        [someOtherObject doSomethingElse];
    }
});
Run Code Online (Sandbox Code Playgroud)

在这种情况下,复制weakSelfstrongSelf(默认情况下很强)是原子的.如果weakSelf是零,strongSelf将是零.如果weakSelf不是nil,strongSelf则不会为nil,并且将成为对象的强引用,防止它在doSomething消息之前被释放.