如何在CoreData中侦听特定实体保存/更新

los*_*ion 6 core-data objective-c ios magicalrecord

我尝试的第一件事是使用FetchedResultsController来解决我的问题.这是FRC的非典型用法,因为我没有更新TableView,我只是用它来确定实体是否在改变,所以我知道何时保存到服务器:

self.fetchedResultsController = [Document MR_fetchAllSortedBy:@"timestamp"
                                                    ascending:NO
                                                withPredicate:[NSPredicate predicateWithFormat:@"report.remoteId != nil && dirty == YES"]
                                                      groupBy:nil
                                                     delegate:self
                                                    inContext:_managedObjectContext];
Run Code Online (Sandbox Code Playgroud)

这里的问题是FRC在关系实体更改时不会收到更新.IE如果report.remoteId从nil变为非nil,我将看不到更新,因为FRC仅侦听Document实体上的更改.此处概述的限制:http://www.mlsite.net/blog/?p = 825和此处更改托管对象属性不会触发NSFetchedResultsController更新表视图

不确定我是否真的想要实施解决方法,因为我使用FRC来做它本来不应该做的事情.我不认为苹果会修复这个限制,所以我真的不想将一个圆形钉子撞到一个方孔来解决我的问题.

几个选项

在保存实体后在代码中触发通知,然后在其他地方侦听.我唯一不喜欢的是程序员要做到这一点并保持最新状态,即如果有人出现并将实体保存在另一个地方,他们必须记得发出通​​知.

要么

侦听保存到默认MOC.这就是我真正想做的事情.像这样的东西:

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

- (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)

这是我的两难困境.这将听取默认MOC上的所有更改.我真的只关心几个实体的变化.所以,是的,我可以过滤掉每次通话中我关心的实体.但是,我有一个案例,我在其中保存了大量我不关心的其他实体.这意味着NSManagedObjectContextObjectsDidChangeNotification将触发一个吨,大部分时间我都不在乎.我不想通过不断收到此通知并花时间过滤掉我不关心的所有实体来减慢我的应用程序.

有没有办法监听特定的实体保存?在CoreData或MagicalRecord中?

如果答案是否定的,是否有一个很好的选择来听取特定实体(及其关系)的变化?

Tom*_*mmy 10

没有办法听取对特定实体集的更改; 捕获NSManagedObjectContextObjectsDidChangeNotification(或已经或将要保存)和过滤是正确的方法,但需要注意的是,如果您正在讨论实体的特定实例,则键值观察也是一种选择.

然而,值得观察的是,它NSManagedObjectID是线程安全的,并提供了一个吸气剂NSEntityDescription.所以你可以,例如

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

    NSMutableArray *objectIDs = [NSMutableArray array];
    [objectIDs addObjectsFromArray:[updatedObjects.allObjects valueForKey:@"objectID"]];
    [objectIDs addObjectsFromArray:[deletedObjects.allObjects valueForKey:@"objectID"]];
    [objectIDs addObjectsFromArray:[insertedObjects.allObjects valueForKey:@"objectID"]];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(){
        NSSet *affectedEntities = [NSSet setWithArray:[objectIDs valueForKeyPath:@"entity.name"]];

        if([affectedEntities containsObject:@"InterestingEntity"]) {
            // get back onto the main thread and do some proper work;
            // possibly having collated the relevant object IDs here
            // first — whatever is appropriate
        }
    });
}
Run Code Online (Sandbox Code Playgroud)