Messaging a __weak object?

前端 未结 2 925
[愿得一人]
[愿得一人] 2021-02-02 16:50

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:

2条回答
  •  醉梦人生
    2021-02-02 17:41

    You asked:

    Assuming weakSelf is non-nil when the message is sent, might it be deallocated while doSomeAction is working or is it guaranteed to remain valid until doSomeAction 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).

提交回复
热议问题