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
weakSelfis non-nilwhen the message is sent, might it be deallocated whiledoSomeActionis working or is it guaranteed to remain valid untildoSomeActionreturns?
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).