如何正确地解决"在ARC模式下弱接收器可能无法预测为空"

gri*_*eak 18 cocoa cocoa-touch automatic-ref-counting

我在xcode中打开了一个新标志并收到警告"在ARC模式下弱接收器可能无法预测为空".这让我感到困惑,因为因为它可能是零.

gri*_*eak 25

我在一周前问过这个问题并且没有得到答复,但Greg Parker在邮件列表上回答了这个问题.所以我转发答案.

我们添加了这个警告,因为我们在实践中看到了许多微妙且难以调试的问题.

建议的做法是将弱变量读入一个强大的局部变量,然后使用局部变量.

  • 格雷格帕克

在我这个问题的第一个版本中,我发布了类似的内容,我认为测试nil应该已经足够了

if (self.rootViewController) {
    [self.rootViewController controllerWillChangeContent:controller];
}
Run Code Online (Sandbox Code Playgroud)

问题是self.rootViewController可以在检查nil和完成调用方法之间的空间中成为nill.我们被告知要做的是分配一个强大的本地参考并使用它

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    RootViewController *rootVC = self.rootViewController;
    if (rootVC) {
        [rootVC controllerWillChangeContent:controller];
    }
}
Run Code Online (Sandbox Code Playgroud)

斯蒂芬巴特勒简要地重述了这个警告意图打击的问题

我们试图阻止的是当你在[someMethod]中时对象实例被释放,因为你从一个弱引用中调用它并且没有任何东西强烈地抓住该对象.

  • 如果您向弱引用发送消息,则会显示该消息 (3认同)
  • 看起来简单地将弱引用分配给强引用就足以消除警告.上面第二个例子中的nil检查是不必要的,因为简单地忽略了对nil的消息.nil检查唯一有用的是,如果目标为零,如果结果将被忽略或丢失,则可以跳过很多工作. (2认同)
  • 此外,根据上述引用帖子的[后续](http://lists.apple.com/archives/objc-language/2012/Aug/msg00010.html),它看起来像是警告的真正要点,更少关于将消息捕获到nil以及更多关于在为消息*提供服务时阻止对象*的重新分配.为调用方法的生命保留强有力的参考可以防止这种情况发生. (2认同)