What happens if I send a message to a weak object? Does sending the message possess the object and hold it in memory until return?
I\'m thinking of this pattern:
You asked:
Assuming
weakSelf
is non-nil
when the message is sent, might it be deallocated whiledoSomeAction
is working or is it guaranteed to remain valid untildoSomeAction
returns?
Yes, not only does it remain valid until doSomeAction
returns, it is retained for the rest of the block, too. Consider the following:
- (void)dealloc
{
NSLog(@"%s", __FUNCTION__);
}
- (void)startBackgroundOperation
{
__weak MyObject * weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[weakSelf doSomeAction];
sleep(5);
[weakSelf doSomeAction2];
});
sleep(1);
}
- (void)doSomeAction
{
NSLog(@"%s", __FUNCTION__);
}
- (void)doSomeAction2
{
NSLog(@"%s", __FUNCTION__);
}
In this example, I make sure that the object was in scope when the block starts, but let it fall out of scope between doSomeAction
and doSomeAction2
, but the block appears to retain it for the completion of the block. But if I comment out the invocation of doSomeAction
, the weak
reference is nil
by the time it gets to doSomeAction2
, just as you'd expect.
As an aside, in WWDC 2011 - #322 - Objective-C Advancements In-Depth, they point out (about 27:00 min into the video), they point out that if you're dereferencing weakSelf
, you should have a local strong reference inside the dispatch block to protect yourself in race condition, thus:
__weak MyClass *weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
MyClass *strongSelf = weakSelf;
if (strongSelf)
[strongSelf->myView doSomeViewAction];
});
That will retain it for the duration of the block (assuming it wasn't already deallocated by the time the block was executed).