2010-03-17 60 views
57

我有一个NSManagedObjectContext,其中有一些NSManagedObjects的子类,这些子类是其他的容器。我想要做的就是观察一个顶级对象,通知它的任何属性,关联或它所包含的任何对象的属性/关联的任何变化。如何跟踪/观察子图内的所有更改?

使用上下文的'hasChanges'不能给我足够的粒度。对象的isUpdated方法只适用于给定的对象(而不是其关联中的任何东西)。是否有一种方便的(也许是基于KVO的)是否可以观察局限于子图的上下文中的变化?

回答

129

您将需要倾听NSManagedObjectContextObjectsDidChangeNotification以获取对您的数据模型的所有更改。这可以通过使用类似下面的代码来完成:

[[NSNotificationCenter defaultCenter] 
     addObserver:self 
     selector:@selector(handleDataModelChange:) 
      name:NSManagedObjectContextObjectsDidChangeNotification 
      object:myManagedObjectContext]; 

将触发-handleDataModelChange:任何更改myManagedObjectContext上下文。

-handleModelDataChange:方法会是这个样子:

- (void)handleDataModelChange:(NSNotification *)note 
{ 
    NSSet *updatedObjects = [[note userInfo] objectForKey:NSUpdatedObjectsKey]; 
    NSSet *deletedObjects = [[note userInfo] objectForKey:NSDeletedObjectsKey]; 
    NSSet *insertedObjects = [[note userInfo] objectForKey:NSInsertedObjectsKey]; 

    // Do something in response to this 
} 

正如你所看到的,通知中包含的信息在其管理对象进行了更新,删除和插入。根据这些信息,您应该能够响应您的数据模型更改。

+0

谢谢!我不知道这个通知。每次发送通知时,必须执行搜索似乎仍然是大规模的矫枉过正。也就是说,我不确定苹果如何优化它。从根本上讲,它仍然是一个图形遍历。 – 2010-03-19 16:23:34

+4

如果您使用NSPredicate筛选这些对象,它实际上是非常高效的,因为所有内容都在内存中。我在iPhone的几个应用程序中使用这个解决方案,并且在这个领域还没有出现性能瓶颈。 – 2010-03-24 14:34:04

+0

嗯,使用NSPredicate很好的呼叫。没有想到这一点。 – 2010-03-24 18:42:30

19

这里有一个简单的例子,在斯威夫特:

NotificationCenter.default.addObserver(forName: .NSManagedObjectContextObjectsDidChange, object: nil, queue: nil) { note in 
     if let updated = note.userInfo?[NSUpdatedObjectsKey] as? Set<NSManagedObject>, updated.count > 0 { 
      print("updated: \(updated)") 
     } 

     if let deleted = note.userInfo?[NSDeletedObjectsKey] as? Set<NSManagedObject>, deleted.count > 0 { 
      print("deleted: \(deleted)") 
     } 

     if let inserted = note.userInfo?[NSInsertedObjectsKey] as? Set<NSManagedObject>, inserted.count > 0 { 
      print("inserted: \(inserted)") 
     } 
    } 
+3

通常,需要跟踪返回值'let observation = NSNotificationCenter.defaultCenter()。addObserverForName(..){..}'通过调用'NSNotificationCenter.defaultCenter()来停止观察。removeObserver(observation) '。 – 2016-09-06 09:33:00

+1

@DanBeaulieu,如果你已经使用了基于阻塞的版本'NSNotificationCenter.defaultCenter()。addObserverForName(..){..}',你需要保持返回的观察结果。 – 2017-01-29 10:43:02

+0

@LevLandau我将撤消我的编辑和阅读,谢谢通知 – 2017-01-29 16:55:20

0

对我来说只是失去了以下两个FUNC,也许这节省小时有人

func controllerWillChangeContent(controller: NSFetchedResultsController) { 
    tableView.beginUpdates() 
} 

func controllerDidChangeContent(controller: NSFetchedResultsController) { 
    tableView.endUpdates() 
} 
+2

这与问题无关。 – rmaddy 2016-12-12 22:26:30