如何跟踪/观察子图中的所有更改?

Dav*_*ney 58 iphone core-data nsmanagedobject nsmanagedobjectcontext

我有一个NSManagedObjectContext,其中我有许多NSManagedObjects的子类,有些是其他人的容器.我想要做的是观察一个顶级对象,通知它对任何属性,关联或它包含的任何对象的属性/关联的任何更改.

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

Bra*_*son 129

您将需要倾听以获取NSManagedObjectContextObjectsDidChangeNotification对数据模型的所有更改.这可以使用如下代码完成:

[[NSNotificationCenter defaultCenter] 
      addObserver:self 
         selector:@selector(handleDataModelChange:) 
             name:NSManagedObjectContextObjectsDidChangeNotification 
           object:myManagedObjectContext];
Run Code Online (Sandbox Code Playgroud)

这将触发-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
}
Run Code Online (Sandbox Code Playgroud)

如您所见,通知包含有关更新,删除和插入哪些托管对象的信息.根据该信息,您应该能够根据数据模型的变化采取行动.

  • 您没有提到这一点,但我想明确指出,您无法使用此通知向对象发出保存.它在processPendingChanges期间发布,在处理完更改之后,但在安全地调用save:之前. (6认同)
  • 小心:NSNotification的userInfo字典中的对象实际上是NSSet类型而不是NSArray! (5认同)
  • 如果你使用NSPredicate来过滤这些对象,它实际上是非常高效的,因为一切都在内存中.我在iPhone的几个应用程序中使用此解决方案,并且在该领域尚未出现性能瓶颈. (4认同)
  • 您还可以使用通知`NSManagedObjectContextDidSaveNotification`在每次保存到上下文后过滤更改. (4认同)

Ili*_*rim 19

这是Swift中的一个简单示例:

    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)")
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 通常需要跟踪返回值`let observation = NSNotificationCenter.defaultCenter().addObserverForName(..){..}`以便能够通过调用`NSNotificationCenter.defaultCenter()来停止观察.removeObserver(观察)` . (3认同)