[英]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.