[英]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,并且doSomething
和doSomethingElse
都不会实际运行。
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
. 因此,您的代码可能使用引用为nil
的weakSelf
执行。 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.