11

每次我必须在这样的块内使用全局变量或属性时:

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

我必须像这样重写

BOOL *iis = isItSaving;
id myself = self;

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

否则 Xcode 会抱怨“在此块中强烈捕获自我可能会导致保留周期......

它甚至抱怨 BOOL 变量?

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

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

这东西很丑。我正在使用 ARC。

4

3 回答 3

21

该问题仅在self从块内显式或隐式引用时发生。访问全局变量时不会发出警告。

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

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

typeof(self) __weak weakSelf = self;

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

...而且,是的,这是块的一个丑陋的部分。

于 2013-04-17T18:53:02.017 回答
4

利用__unsafe_unretained typeof(self) weakSelf = self;

于 2013-07-23T06:22:13.070 回答
0

除了@NikolaiRuhe 的回复,在您的示例中,在声明属性时

BOOL *iis = isItSaving;
id myself = self;

暗示strong引用,所以使用__weakself 来防止保留循环。然后你可能想知道为什么你需要__strong在块中声明对弱自身的引用,这是为了确保它在块的生命周期内不会被释放,否则weakSelf->isItSaving如果self被释放就会中断。

于 2016-08-12T10:46:09.440 回答