避免“在此块中强烈捕获自我可能会导致保留周期”消息

时间:2013-04-17 18:44:20

标签: objective-c cocoa-touch cocoa objective-c-blocks

每次我必须在块中使用全局变量或属性,如下所示:

self.save = ^(){
  if (isItSaving == NO) {
      [self saveMyFile];
  }
};

我必须重写这个

BOOL *iis = isItSaving;
id myself = self;

self.save = ^(){
  if (iis == NO) {
      [myself saveMyFile];
  }
};

或Xcode会抱怨“在这个区块中强烈捕获自我可能会导致保留周期...

甚至抱怨BOOL变量?

在块之前重新声明所有内容似乎是一种蹩脚的解决方案。

这是正确的方法吗?有优雅的方式吗?

这个东西太丑了。我正在使用ARC。

3 个答案:

答案 0 :(得分:20)

只有在显式或隐式地从块中引用self时才会出现此问题。访问全局变量时没有发出警告。

在你的情况下,你可能访问了一个(布尔)ivar。访问ivar隐式使用self,这就是编译器(正确地)警告您保留周期的原因。

修复保留周期的常用方法是:

typeof(self) __weak weakSelf = self;

self.save = ^() {
    typeof(weakSelf) __strong strongSelf = weakSelf;
    if (strongSelf != nil && ! strongSelf->isItSaving) {
        [strongSelf saveMyFile];
    }
};

......而且,是的,这有点像块的丑陋部分。

答案 1 :(得分:4)

使用__unsafe_unretained typeof(self) weakSelf = self;

答案 2 :(得分:0)

除了@ NikolaiRuhe的回复之外,在你的例子中声明属性

BOOL *iis = isItSaving;
id myself = self;

隐含strong引用,因此请使用__weak self来阻止保留周期。然后你可能想知道为什么你需要在块中声明对弱自我的__strong引用,并且确保它在块的生命期内不会被释放,否则{{如果weakSelf->isItSaving被释放,1}}会中断。