ARC捕获self ...阻塞块内部并在执行之前释放引用

Spa*_*Dog 1 iphone ipad ios objective-c-blocks

我有这个问题:一个块内的块.

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

我将在[self doStuff]和[self doMoreStuff]中出错.错误是在此块中强烈捕获"自我"可能会导致保留周期

你说容易,只需添加

id mySelf = self; 
Run Code Online (Sandbox Code Playgroud)

在第一个块之前并使用mySelf.

不.这不会保存我的问题,只是因为我自己是一个善意的id不会给我一个post属性,第二行需要.所以我需要声明它

MyClass *mySelf = self;
Run Code Online (Sandbox Code Playgroud)

使它像:

MyClass *mySelf = self;

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

好吧,你说,现在self.post.onCompletion行和doMoreStuff不再抱怨了,但我们在onCompletion中有另一个self ...因为这是一个块内的块.我可以重复创建另一个弱引用的过程,这将是弱引用的弱引用

MyClass *internalMyself = mySelf;
Run Code Online (Sandbox Code Playgroud)

并使用

   [internalMyself doStuff];
Run Code Online (Sandbox Code Playgroud)

在我看来这是一个非常可悲的方式来做这个以及更多,当这个方法运行时应用程序挂起.在方法执行之前,正在释放类似引用的内容...

我该如何解决这个问题?

谢谢.


注意:这是编译到iOS 6+

mop*_*led 6

你很亲密.只需更换您的解决方案

MyClass *mySelf = self;

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

__weak MyClass *mySelf = self;

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

第一个解决方案的问题mySelf是未指定weak,因此它的所有权限定符是隐式的__strong(请参阅LLVM的文档).我不确定为什么这会在第一个块中消除警告,但是指定引用__weak将完全消除保留周期.

  • `__weak`仅适用于iOS 5+.如果您需要在ARC上支持iOS 4,则需要使用`__unsafe_unretained` (3认同)