繁体   English   中英

在未调用viewDidLoad的情况下调用了Dealloc(删除KVO观察器时崩溃)

[英]Dealloc called without viewDidLoad being called (crash on removing KVO observer)

我正在使用UITabBarController ,并且我的第三个选项卡观察到单例数据存储中的数组(在viewDidLoad实现)。

当前,如果我刚刚注销(并从App Delegate更改根视图控制器),则在该第三个选项卡上调用dealloc并显示消息“无法删除键路径“ X”的观察者,因为它未注册为”时,应用程序将崩溃观察者。

使用断点,我看到从来没有在第3个选项卡上调用viewDidLoad ,但是注销时却调用了dealloc。 到底是怎么回事? 我假设UITabBarController在进入情节UITabBarController持有对第3个选项卡的引用,但没有“加载”该选项卡。 当我释放选项卡栏控制器时,iOS对其调用了dealloc。

我应该使用布尔值来跟踪viewDidLoad执行情况,还是尝试使用@try语句删除观察者? 是否有总体上更好的设计?

不要使用@try 应始终将Objective-C中的异常视为程序员错误 ,并且应是致命的。

如您所说,请使用-viewDidLoad设置的布尔ivar来避免这种情况。


该视图尚未加载,因为仅在需要显示时才加载视图。


原始的KVO可能是危险且笨拙的。 尽管不需要回答这个问题,但ReactiveCocoa可以显着改善KVO体验。

在视图首次出现之前调用viewDidLoad UITabBarController正在创建相关的UIViewController ,但是在创建过程中不会加载视图。 当用户第一次访问该选项卡时,它是按需加载的。

删除KVO是有问题的,我认为您不能避免在dealloc使用@try 我建议使用KVOController :它相当容易使用,并且还可以为您处理所有边缘情况。

可能找到了更好的解决方案。 我在initWithCoder:(NSCoder *)aDecoder方法中添加了观察者,该方法在加载父UITabController时调用。 我正在使用情节提要,这可能就是为什么我需要调用重写此方法而不是常规init 立即执行此操作,而无需BOOL标志或@try ,也不会崩溃。

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super initWithCoder:aDecoder]) {
        [anObject addObserver:self forKeyPath:aKeyPath options:0 context:NULL];
    }
    return self;
}

使用标志设置是否已设置KVO。 使用@try可能会导致内存管理问题,具体取决于应用程序的状态。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM