ARC capturing self… block inside a block and reference being released before execution

柔情痞子 提交于 2019-12-13 00:25:06

问题


I have this problem: a block inside a block.

  self.createStuff = ^ (NSString *text) {       
        self.post.onCompletion = ^(NSURLResponse *response, NSData *data, NSError *error){
                [self doStuff];  // error here
        };
        [self doMoreStuff];  // error here
  };

I will have errors in [self doStuff] and on [self doMoreStuff]. The error is capturing 'self' strongly in this block is likely to lead to a retain cycle

Easy you say, just add

id mySelf = self; 

before the first block and use mySelf instead.

Nope. This will not save my problem, simply because mySelf being of kind id will not give me a post property, needed by the second line. So I need to declare it like

MyClass *mySelf = self;

Making it like:

MyClass *mySelf = self;

  self.createStuff = ^ (NSString *text) {       
        mySelf.post.onCompletion = ^(NSURLResponse *response, NSData *data, NSError *error){
                [self doStuff];  // error here
        };
        [mySelf doMoreStuff];  
  };

OK, you say, now the self.post.onCompletion line and doMoreStuff are not complaining anymore, but we have another self inside onCompletion... because this is a block inside a block. I can repeat the process creating another weak reference like and this will have to be a weak reference to a weak reference

MyClass *internalMyself = mySelf;

and use

   [internalMyself doStuff];

this seems to me to be a pretty pathetic way to do this and more, the app hangs when this method runs. Something like the reference is being deallocated before the method executes...

How do I solve this charade?

thanks.


note: this is being compiled to iOS 6+


回答1:


You're pretty close. Just replace your solution

MyClass *mySelf = self;

self.createStuff = ^ (NSString *text) {       
     mySelf.post.onCompletion = ^(NSURLResponse *response, NSData *data, NSError *error) {
          [self doStuff];  // error here
     };
     [mySelf doMoreStuff];  
};

with

__weak MyClass *mySelf = self;

self.createStuff = ^ (NSString *text) {       
     mySelf.post.onCompletion = ^(NSURLResponse *response, NSData *data, NSError *error) {
          [self doStuff];  // error here
     };
     [mySelf doMoreStuff];  
};

The problem with the first solution is that mySelf isn't designated weak, so it's ownership qualifier is implicitly __strong (see LLVM's documentation). I'm not sure why this quiets the warning in the first block, but designating the reference __weak will fully remove the retain cycle.



来源:https://stackoverflow.com/questions/14667610/arc-capturing-self-block-inside-a-block-and-reference-being-released-before-e

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