我有一个自动合成的readonly
& weak
财产:
@property (nonatomic, readonly, weak) KTWindowController* windowController;
我分配合成的ivar,然后将其添加到数组中:
_windowController = [KTWindowController controller];
[self addSubController:_windowController];
这在Debug版本中工作正常。但我得到一个报告,在发布(ad hoc)版本中,这将立即使_windowController
无效,然后它会尝试将nil添加到数组中,从而导致应用程序崩溃。
与Debug版本相比,发布(ad hoc)版本中的哪些特定设置(优化级别?)会改变此行为?
令我感到奇怪的是,这种行为会从Debug版本变为Release版本。但我能够重现这种行为,它实际上是有意义的 - 只是当它与调试版本中发生的事情不一致时。
建议的解决方法:
KTWindowController* windowController = [KTWindowController controller];
[self addSubController:windowController];
_windowController = windowController;
除了如上所示使用本地变量之外,在这种情况下,您会推荐哪种解决方法?
答案 0 :(得分:1)
当您将属性声明为弱时,您承诺其他一些对象会负责所有权。这就是弱的意思。当你违反这一点时,会发生不好的事情。所以,例如,当你写:
KTWindowController* windowController = [KTWindowController controller];
[self addSubController:windowController];
_windowController = windowController;
您正在履行您的义务:强大的临时变量windowController
处理此方法中的所有权,然后windowController subController
处理所有权。
当你写
时 _windowController = [KTWindowController controller];
你没有做你应许做的事。 _windowController很弱,所以其他人正在管理生命周期。但看!没有人管理一生!所以我们可以随时摆脱弱变量。优化器会在您的发布版本中查看此内容并说,
喂!这家伙说他不关心这个窗户控制器是否存在或生死,只要没有其他人关心。有些人!但这不关我的事。但是看看这个:因为他不在乎,我根本不需要做到这一点!或者,无论如何,我可以立即摆脱它。
编译器正在做你想说的事情。
您确定要将此作为弱房产吗?每当我在我的代码中看到这一点时,我都会检查该属性是否真的应该是弱的;通常,我想要一个强大的财产。
答案 1 :(得分:0)
我发现将优化级别从None (-O0)
更改为Fast (-O, O1)
会引发此问题。
As mentioned here,这种行为是可以预期的。它确实应该是编译器警告。
我最终通过将分配移动到一行来合并解决方法中的额外行,这也适用:
// extra local var to prevent ARC from nil'ing the weak var right away in release
KTWindowController* windowController = _windowController =
[KTWindowController controller];
[self addSubController:windowController];