Do I need to check if weak self is nil in blocks?
I create weakSelf pointer like:
__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:
At
THE LINE OF INTEREST
, some other thread might clear the last strong reference toself
, at which pointweakSelf
is set to nil. So thedoSomething
message gets sent to nil, which is “safe” (it does nothing), but might not be what you expected!It's worse if you want to take a different action when
weakSelf
is nil, e.g.In this case, between the time the block verifies that
weakSelf
is not nil and the time it sends thedoSomething
message,weakSelf
might become nil, and neitherdoSomething
nordoSomethingElse
will actually run.The correct solution is this:
In this case, copying
weakSelf
tostrongSelf
(which is strong by default) is atomic. IfweakSelf
was nil,strongSelf
will be nil. IfweakSelf
was not nil,strongSelf
will not be nil, and will be a strong reference to the object, preventing it from being deallocated before thedoSomething
message.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
.Therefore it is possible that your code is executed with a
weakSelf
that refersnil
. But this is no reason to check for it at all. Especially in Objective-C you use a defined behavior, if you send a messagenil
. I. e. it is perfect code, if you set a property using anil
reference. It simply goes to nowhere.Of course sometime you do not want to interact with
nil
. In such a case you have to check for it.BTW: You need
weakSelf
only in some, rarely circumstances. It is an urban legend that in closures in general references toself
has to be weak to prevent retain cycles. It has not been true, it is not true and it will never be true.It seems quite unnecessary since calling a message on nil is a no-op. (Nothing happens)
The only reason I can think you might want to do this is if other messages (not on self) shouldn't be called