我正在使用UITabBarController
,我的第3个标签在单个数据存储上观察一个数组(在viewDidLoad
中实现)。
目前,如果我只是注销(并从App Delegate
更改根视图控制器),则在第3个选项卡上调用dealloc
时,应用程序将崩溃并显示消息"无法删除观察者关键路径" X"因为它没有注册为观察员。
使用断点,我发现在第3个选项卡上永远不会调用viewDidLoad
,但是当我退出时会调用dealloc。到底是怎么回事?我假设当我进入故事板时UITabBarController
持有对第3个标签的引用,但是没有"加载"那个标签。然而,当我发布标签栏控制器时,iOS会调用dealloc。
我应该使用布尔来跟踪viewDidLoad
执行,还是尝试使用@try
语句删除观察者?是否有更好的设计呢?
答案 0 :(得分:3)
请勿使用@try
。 Objective-C中的异常应始终为considered programmer error,并且应该是致命的。
正如您所说,使用-viewDidLoad
中的布尔值设置来避免这种情况。
尚未加载视图,因为只有在需要显示视图时才会加载视图。
原始KVO可能是危险和笨重的。虽然不需要回答这个问题,但ReactiveCocoa显着改善了KVO体验。
答案 1 :(得分:2)
viewDidLoad
。 UITabBarController
正在创建相关的UIViewController
,但视图未在创建期间加载。当用户第一次访问选项卡时,它会按需加载。
KVO删除有问题,我认为您无法避免在@try
中使用dealloc
。我建议使用KVOController:它相当容易使用,它也可以处理所有边缘情况。
答案 2 :(得分:1)
可能找到了更好的解决方案。我在方法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;
}
答案 3 :(得分:0)
使用标志设置是否已设置KVO。使用@try可以根据应用程序的状态创建内存管理问题。