让我们想象一个基本的iPhone应用程序,它有一个表视图来显示人员列表,还有一个详细信息视图来更改嵌入导航控制器中的人员的姓名。
我正在使用KVO在我的表视图控制器中得到通知,一个人的名字在细节控制器中被更改了。
我的问题是在何时/何处添加和删除我的表视图控制器作为每个person对象的name
的观察者。
我的方法:
@implementation PeopleTableViewController
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
Person *person = ...; // person for index path
[person addObserver:self forKeyPath:@"name" options:0 context:(__bridge void *)(PERSON_NAME_CTX)];
}
- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
Person *person = ...; // person for index path
[person removeObserver:self forKeyPath:@"name"];
// This is not called when the view is removed from the hierarchy
// Can't use viewDidDisappear: because we are using a navigation controller
// and tableView:willDisplayCell: is not called when we return from the details controller
}
- dealloc {
// See comment in didEndDisplayingCell:
for (UITableViewCell *cell in self.tableView.visibleCells) {
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
Person *person = ...; // person for index path
[person removeObserver:self forKeyPath:@"name"];
}
}
由于导航控制器的原因,事情有点棘手,因为从视图层次结构中删除视图时不会调用tableView: didEndDisplayingCell
。我不能删除viewWillDisappear:
中的观察者,因为当用户从细节控制器返回时,我仍然需要观察person对象的变化。
删除dealloc
中的观察者似乎有效。我的问题是:这样做对吗?
通常您应该分别对viewWillAppear/viewWillDisappear方法调用addObserver/removeObserver,因为dealloc方法与这些调用不平衡(我的意思是可以比上面的方法调用几次)。也许最好的解决方案之一是使用NSFetchedResultsController来跟踪对数据源的任何更改。