Reference to self inside block

我怕爱的太早我们不能终老 提交于 2019-11-30 15:51:40

Yes, it creates a retain cycle. Does it cause problems? Maybe.

If the API supports it, you can reset the handlers, which will break the retain cycle manually:

[operation setCompletionBlockWithSuccess:nil failure:nil];

Or you can use a weak reference. However, you say you tried a weak reference, and it crashed. A weak reference is guaranteed to be either nil at the start of a message, or remain valid until the message has been processed. In other words, consider...

__weak MyRequest *weakSelf = self;
dispatch_async(someQ, ^{
    [weakSelf doSomething];
});

If weakSelf is nil when the asynchronous block executes, then "nothing" happens. If it is not nil, then it is guaranteed to be retained at least until doSomething has finished. In effect, it is similar to this:

__weak MyRequest *weakSelf = self;
dispatch_async(someQ, ^{
    { id obj = weakSelf; [weakSelf doSomething]; obj = nil; }
});

Note, however, that if you did this:

__weak MyRequest *weakSelf = self;
dispatch_async(someQ, ^{
    [weakSelf doSomething];
    [weakSelf doSomethingElse];
});

that the object could become nil in-between doSomething and doSomethingElse.

Furthermore, if you access an instance variable via a weak reference, you are just asking for a SEGV:

__weak MyRequest *weakSelf = self;
dispatch_async(someQ, ^{
    foo = weakSelf->someIVar; // This can go BOOM!
});

Thus, if your handler is accessing the weak reference for a single message, then you should be fine. Anything else should do the "Weak-Strong-Dance."

__weak MyRequest *weakSelf = self;
dispatch_async(someQ, ^{
    MyRequest *strongSelf = weakSelf;
    if (!strongSelf) return;
    [strongSelf doSomething];
    [strongSelf doSomethingElse];
    foo = strongSelf->someIVar;
});

If you think you are following the guidelines, then maybe a more complete source code example, with the crash details would help...

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!