KVO在UITableView中观察模型变化的最佳实践



让我们想象一个基本的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来跟踪对数据源的任何更改。

最新更新