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

时间:2013-02-02 23:19:54

标签: iphone ios ipad objective-c-blocks

我遇到了这个问题:一个区块内的一个区块。

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

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

很容易说,只需添加

id mySelf = self; 

在第一个块之前,改为使用mySelf。

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

MyClass *mySelf = self;

使它像:

MyClass *mySelf = self;

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

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

MyClass *internalMyself = mySelf;

并使用

   [internalMyself doStuff];

在我看来这是一个非常可悲的方式来做这个,更多,这个方法运行时应用程序挂起。在方法执行之前,类似于引用的东西被释放...

如何解决这个问题?

感谢。


注意:这是编译到iOS 6 +

1 个答案:

答案 0 :(得分:6)

你非常接近。只需更换您的解决方案

MyClass *mySelf = self;

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

__weak MyClass *mySelf = self;

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

第一个解决方案的问题是mySelf未指定为weak,因此所有权限定符隐含__strongsee LLVM's documentation)。我不确定为什么这会在第一个块中消除警告,但是指定引用__weak将完全删除保留周期。