块中的弱自我

时间:2015-06-17 15:45:44

标签: ios objective-c weak-references weak-ptr

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

我创建了weakSelf指针,如:

__weak typeof(self) weakSelf = self;

在块的开头我做

if(!weakSelf){return;}

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

3 个答案:

答案 0 :(得分:11)

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

问题在于:

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

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

如果你想在weakSelf为零时采取不同的行动,情况会更糟,例如

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

在这种情况下,在块验证weakSelf不是nil的时间与发送doSomething消息的时间之间,weakSelf可能会变为零,doSomething也不会并且doSomethingElse实际上会运行。

正确的解决方案是:

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

在这种情况下,将weakSelf复制到strongSelf(默认为强)是原子的。如果weakSelf为零,strongSelf将为零。如果weakSelf不是nil,strongSelf将不会为nil,并且将成为该对象的强引用,从而阻止它在doSomething消息之前被取消分配。

答案 1 :(得分:3)

似乎没有必要,因为在nil上调用消息是一种无操作。 (什么也没发生)

^{
    [weakSelf doSomething]; //Does nothing if weakSelf is nil
}

我认为您可能想要这样做的唯一原因是,如果不应该调用其他消息(不在自己身上)

^{
    // Here I don't want to add weakSelf as an observer if it's nil
    if (!weakSelf) return;

    [OtherClass addObserverForSomething:weakSelf];
}

答案 2 :(得分:-2)

弱引用不保留引用的对象。如果没有其他人保留它,则释放该对象,弱引用引用nil

因此,您的代码可能会使用引用weakSelf的{​​{1}}执行。但这根本没有理由检查它。特别是在Objective-C中,如果发送消息nil,则使用已定义的行为。 I. e。如果您使用nil引用设置属性,它是完美的代码。它只是无处可去。

当然有时您不想与nil互动。在这种情况下,你必须检查它。

顺便说一句:你只需要在一些很少的情况下nil。这是一个城市传说,在封闭中一般提到weakSelf必须弱,以防止保留周期。它不是真的,它不是真的,它永远不会成真。