我有一个符合KVO标准的简单Viewcontroller,其中包含以下内容:
- (void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self addObserver:self forKeyPath:@"importStuff" options:0 context:NULL];
[self addObserver:self forKeyPath:@"importStuffFailed" options:0 context:NULL];
}
- (void) viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self removeObserver:self forKeyPath:@"importStuff"];
[self removeObserver:self forKeyPath:@"importStuffFailed"];
}
我遇到的问题是,有时用户报告以下错误:
Cannot remove an observer <MyViewController 0x145d0c8d0> for the key path "importStuff" from <MyViewController 0x1741b2280> because it is not registered as an observer.
在代码中的其他任何地方都不会调用addObserver调用。这是关于生命周期的遗失吗?是不是viewDidAppear保证被调用一次(所以它应该正确注册键?)
答案 0 :(得分:11)
Apple Docs说当视图仅可见时,有一种方法可以添加观察者。根据图1 - 有效状态转换,您可以使用对viewWillAppear
/ viewWillDisppear
来添加和删除观察者。同时,您可以使用init
/ dealloc
对,但不能使用viewDidLoad
/ dealloc
- 视图无法加载,但控制器已取消分配。
您的代码应为:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self addObserver:self forKeyPath:@"importStuff" options:0 context:NULL];
[self addObserver:self forKeyPath:@"importStuffFailed" options:0 context:NULL];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self removeObserver:self forKeyPath:@"importStuff"];
[self removeObserver:self forKeyPath:@"importStuffFailed"];
}
答案 1 :(得分:3)
无法保证viewDidAppear
每次都与viewWillDisappear
匹配。这意味着您的KVO注册/注销可能不平衡且不确定。您应该以{{1}}和viewDidLoad
等有保证的配对方式执行KVO注册/取消注册。