Let’s say my class looks like
@interface MyClass {
MyObject* _object;
dispatch_queue_t _queue;
}
-(void)myBlocksUsingMethod;
@end
Ignoring the semantics of initializing the queue, now I implement
-(void)myBlockUsingMethod {
dispatch_async(_queue, ^{
[_object doSomething];
});
}
As the above code stands, is retaining self in the block ok?
I could rewrite the block like
-(void)myBlockUsingMethod {
__weak MyClass* weakSelf = self;
dispatch_async(_queue, ^{
MyClass* strongSelf = weakSelf;
[strongSelf._object doSomething];
});
}
But now is it necessary to test if strongSelf == nil in this situation given that my _queue is an iVar of the object I’m retaining?
Also, what happens if my doSomething method were to push another block that references self onto the same queue? Will that cause a retain cycle?
To answer the question in the title: Yes, there are many reasons to do this. You may know for certain that the object will outlive the block, or you may want to create a retain cycle that will be broken manually at a specific time later.
However, in your code, you are doing something quite wrong. The first method (the one that creates the implicit strong reference to self) should generate a warning.
The second one should not compile. You have this:
which is invoking a property named
_objectand I doubt that’s the case. So, maybe you meant this:in which case, you will be fine because if
strongSelfisnilthen a message sent tonileffectively does nothing.Or, if there is no property, maybe you really mean this:
in which case, your program will blow up if strongSelf is nil, because this is not sending a message to
nilbut dereferencing a null pointer. If you do the latter, you need to check fornilexplicitly.Since you do not access
_queuein the block, that access is fine. Any direct access of an iVar inside a block must either create a retain cycle to make sure the object is still alive, or it must play the weak-strong-dance and check for nil.If you use the object in multiple lines, you also need to do the weak-strong-dance because the weak object could dealloc in between accesses (the runtime guarantees that if a __weak is not nil, and accepts a message, that it will stay alive until that message has been handled).