【问题标题】:NSFetchedResultsControllerDelegate instead of KVO - but how to know what changed?NSFetchedResultsControllerDelegate 而不是 KVO - 但如何知道发生了什么变化?
【发布时间】:2013-12-15 19:19:53
【问题描述】:

根据KVO observing of NSMangedObject in a UITableViewCell,应该实现 NSFetchedResultsControllerDelegate 而不是使用 KVO 来观察使用 NSFetchedResultsController 获取的托管对象的属性更改。

但是如何确定哪些属性发生了变化以及哪些对象发生了变化?

我有数据更新通过套接字更新我的托管对象,并希望我的 UI 在列出对象的某些属性发生变化时相应地更新。例如,我不想重绘整个表格或每个单元格,只重绘显示已更改属性值的标签。

这是可行的,还是我应该求助于 KVO 但以某种方式对其进行优化?

【问题讨论】:

  • 您对 FRC 并担任其代表有什么特殊问题吗?
  • 不,我还没试过。在托管对象上设置了很多观察者后,我开始面临崩溃,并遇到了上面链接的问题。

标签: ios objective-c uitableview nsfetchedresultscontroller key-value-observing


【解决方案1】:

您不应该使用 KVO 来更新 CoreData 对象。原因是:可以从两个不同的上下文中检索相同的对象记录,而 KVO 观察只会从视图的上下文中通知您该对象,让您不知道在不同上下文中对同一对象进行的更新。使用 fetched results 控制器中的委托方法允许您响应从其他上下文对对象所做的更改。下面是取自“CoreDataBooks”示例项目的示例代码,是使用获取的结果控制器响应更改的正确方法:

/*
 NSFetchedResultsController delegate methods to respond to additions, removals and so on.
 */
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {

    // The fetch controller is about to start sending change notifications, so prepare the table view for updates.
    [self.tableView beginUpdates];
}


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {

    UITableView *tableView = self.tableView;

    switch(type) {

        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;

        case NSFetchedResultsChangeUpdate:
            [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            [tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
    }
}


- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{    
    switch(type) {

        case NSFetchedResultsChangeInsert:
            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;

        case NSFetchedResultsChangeDelete:
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
    }
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {

    // The fetch controller has sent all current change notifications, so tell the table view to process all updates.
    [self.tableView endUpdates];
}

【讨论】:

  • 那么处理对象属性值改变的正确方法是响应NSFetchedResultsChangeUpdate,并重新配置整个单元格?
  • 好的,我会试一试,希望它能处理频繁的更新。我猜你的答案是正确的,如果有必要我会调整更新。感谢您的快速回答!
  • 它是否仅在保存到持久存储或其他内容时更新?这些对象使用 restkit 映射进行更新,但 NSFetchedResultsControllerDelegate 对这些更新没有任何反应。 KVO 触发良好。我现在最终使用了 KVO,因为在我调整它之后它似乎运行得很好。也许这一切都在同一个背景下,因为它正在工作?
  • 对,只有在对对象所做的更改保存到持久存储后,它才会更新对象。如果您在同一上下文中的多个位置仅使用一组对象,那么是的,简单的 KVO 应该可以正常工作。然而,一旦你开始使用多个上下文并且在多个地方需要相同的对象,你应该使用这些委托方法来更新你的对象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-18
  • 2011-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多