简体   繁体   English

块中的弱自我

[英]Weak Self in Blocks

Do I need to check if weak self is nil in blocks? 我是否需要检查弱自我是否在块中为零?

I create weakSelf pointer like: 我创建了weakSelf指针,如:

__weak typeof(self) weakSelf = self;

and in the beginning of the blocks I do 在我做的块的开头

if(!weakSelf){return;}

is this unnecessary? 这是不必要的吗? or does it depend on whether I coded the rest correctly so that when the self dies, others die too? 或者它取决于我是否正确编码其余部分,以便当自我死亡时,其他人也会死亡?

That check is unnecessary, and is giving you a false sense of security. 这种检查是不必要的,并且给你一种错误的安全感。

Here's the problem: 这是问题所在:

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

At THE LINE OF INTEREST , some other thread might clear the last strong reference to self , at which point weakSelf is set to nil. THE LINE OF INTEREST ,其他一些线程可能会清除对self的最后一个强引用,此时weakSelf设置为nil。 So the doSomething message gets sent to nil, which is “safe” (it does nothing), but might not be what you expected! 所以doSomething消息被发送到nil,这是“安全的”(它什么都不做),但可能不是你所期望的!

It's worse if you want to take a different action when weakSelf is nil, eg 如果你想在weakSelf为零时采取不同的行动, weakSelf ,例如

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

In this case, between the time the block verifies that weakSelf is not nil and the time it sends the doSomething message, weakSelf might become nil, and neither doSomething nor doSomethingElse will actually run. 在这种情况下,在块验证weakSelf不是nil的时间和发送doSomething消息的时间之间, weakSelf可能变为nil,并且doSomethingdoSomethingElse都不会实际运行。

The correct solution is this: 正确的解决方案是:

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

In this case, copying weakSelf to strongSelf (which is strong by default) is atomic. 在这种情况下,将weakSelf复制到strongSelf (默认情况下很强)是原子的。 If weakSelf was nil, strongSelf will be nil. 如果weakSelf为零,则strongSelf将为零。 If weakSelf was not nil, strongSelf will not be nil, and will be a strong reference to the object, preventing it from being deallocated before the doSomething message. 如果weakSelf不是nil, strongSelf将不会是nil,并且将成为对象的强引用,防止它在doSomething消息之前被释放。

It seems quite unnecessary since calling a message on nil is a no-op. 这似乎是非常不必要的,因为在nil上调用消息是一种无操作。 (Nothing happens) (什么都没发生)

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

The only reason I can think you might want to do this is if other messages (not on self) shouldn't be called 我认为你可能想要这样做的唯一原因是不应该调用其他消息(不是自己的)

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

    [OtherClass addObserverForSomething:weakSelf];
}

Weak references do not retain the referred object. 弱引用不保留引用的对象。 If none else is retaining it, the object is released and the weak references refers to nil . 如果没有其他人保留它,则释放该对象,并且弱引用指的是nil

Therefore it is possible that your code is executed with a weakSelf that refers nil . 因此,您的代码可能使用引用为nilweakSelf执行。 But this is no reason to check for it at all. 但这根本没有理由检查它。 Especially in Objective-C you use a defined behavior, if you send a message nil . 特别是在Objective-C中,如果发送消息为nil ,则使用已定义的行为。 I. e. I. e。 it is perfect code, if you set a property using a nil reference. 如果使用nil引用设置属性,它是完美的代码。 It simply goes to nowhere. 它简直无处可去。

Of course sometime you do not want to interact with nil . 当然有时候你不想与nil交互。 In such a case you have to check for it. 在这种情况下,你必须检查它。

BTW: You need weakSelf only in some, rarely circumstances. 顺便说一句:你只需要在一些很少的情况下需要weakSelf It is an urban legend that in closures in general references to self has to be weak to prevent retain cycles. 这是一个城市传说,在封闭中一般提到self必须弱,以防止保留周期。 It has not been true, it is not true and it will never be true. 它不是真的,它不是真的,它永远不会是真的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM