如何使用NSDistributedNotifications在进程之间共享Core Data存储?

Joh*_*her 8 cocoa ipc core-data

背景

我已经发布了一个关于在进程之间共享Core Data存储的基础知识的问题.

我正在尝试实施给出的建议,但我遇到了问题.

我的目标

我有两个过程 - 帮助应用程序和UI.它们共享一个数据存储.当Helper App将新数据保存到商店时,我希望UI更新它的NSManagedObjectContext.

当前的计划流程

  1. Helper App Process将数据写入Store.

  2. 在Helper App中,我监听NSManagedObjectContextDidSaveNotification通知.

  3. 保存上下文后,我使用它们的URI表示和NSArchiver对插入,删除和更新的对象进行编码.

  4. 我将NSNotification发送到NSDistributedNotificationCenter,并将此编码字典作为userInfo发送.

  5. UI进程正在侦听保存通知.收到通知后,它会使用NSUnarchiver取消归档userInfo.

  6. 它从给定的URI中查找所有更新/插入/删除的对象,并用NSManagedObjects替换它们.

  7. 它使用更新/插入/删除的对象构造NSNotification.

  8. 我在UI进程的托管对象上下文中调用mergeChangesFromContextDidSaveNotification:传入我在上一步中构建的NSNotification.

问题

插入的对象出现在UI管理对象上下文中,并且它们出现在UI中.问题来自更新的对象.他们只是不更新​​.

我试过的

  1. 最明显的尝试是将Helper App流程中的保存通知传递给UI流程.容易,对吗?好吧,不.分布式通知将不允许我这样做,因为userInfo字典的格式不正确.这就是我正在做所有NSArchiving的原因.

  2. 我已经尝试调用要更新的NSManagedObjects上的refreshObject:mergeChanges:YES,但这似乎没有任何效果.

  3. 我已经尝试在主线程和当前线程上执行mergeChangesFromContextDidSaveNotification:selector.似乎都没有影响结果.

  4. 我尝试过使用mergeChangesFromContextDidSaveNotification:在线程之间,这当然要简单得多,而且效果很好.但我需要在进程之间使用相同的功能.

备择方案?

我在这里错过了什么吗?我一直觉得我做的比现在要复杂得多,但是经过多次阅读文档并花了几天时间,我看不出任何其他方式来刷新MOC用户界面.

有更优雅的方式吗?或者我只是在我的代码中某处犯了一个愚蠢的错误?

代码

我试图尽可能让它变得可读,但它仍然是一团糟.抱歉.

帮助应用程序代码

   -(void)workerThreadObjectContextDidSave:(NSNotification *)saveNotification {
        NSMutableDictionary *savedObjectsEncodedURIs = [NSMutableDictionary dictionary];
        NSArray *savedObjectKeys = [[saveNotification userInfo] allKeys];

        for(NSString *thisSavedObjectKey in savedObjectKeys) {
            // This is the set of updated/inserted/deleted NSManagedObjects.
            NSSet *thisSavedObjectSet = [[saveNotification userInfo] objectForKey:thisSavedObjectKey];
            NSMutableSet *thisSavedObjectSetEncoded = [NSMutableSet set];

            for(id thisSavedObject in [thisSavedObjectSet allObjects]) {
                // Construct a set of URIs that will be encoded as NSData
                NSURL *thisSavedObjectURI = [[(NSManagedObject *)thisSavedObject objectID] URIRepresentation];
                [thisSavedObjectSetEncoded addObject:thisSavedObjectURI];
            }
            // Archive the set of URIs.
            [savedObjectsEncodedURIs setObject:[NSArchiver archivedDataWithRootObject:thisSavedObjectSetEncoded] forKey:thisSavedObjectKey];
        }

        if ([[savedObjectsEncodedURIs allValues] count] > 0) {
            // Tell UI process there are new objects that need merging into it's MOC
            [[NSDistributedNotificationCenter defaultCenter] postNotificationName:@"com.synapticmishap.lapsus.save" object:@"HelperApp" userInfo:(NSDictionary *)savedObjectsEncodedURIs];
        }
    }
Run Code Online (Sandbox Code Playgroud)

UI代码

-(void)mergeSavesIntoMOC:(NSNotification *)notification {
    NSDictionary        *objectsToRefresh        = [notification userInfo];
    NSMutableDictionary *notificationUserInfo    = [NSMutableDictionary dictionary];
    NSArray *savedObjectKeys = [[notification userInfo] allKeys];

    for(NSString *thisSavedObjectKey in savedObjectKeys) {
        // Iterate through all the URIs in the decoded set. For each URI, get the NSManagedObject and add it to a set.
        NSSet *thisSavedObjectSetDecoded = [NSUnarchiver unarchiveObjectWithData:[[notification userInfo] objectForKey:thisSavedObjectKey]];
        NSMutableSet *savedManagedObjectSet = [NSMutableSet set];

        for(NSURL *thisSavedObjectURI in thisSavedObjectSetDecoded) {
            NSManagedObject *thisSavedManagedObject = [managedObjectContext objectWithID:[persistentStoreCoordinator managedObjectIDForURIRepresentation:thisSavedObjectURI]];
            [savedManagedObjectSet addObject:thisSavedManagedObject];
            // If the object is to be updated, refresh the object and merge in changes.
            // This doesn't work!
            if ([thisSavedObjectKey isEqualToString:NSUpdatedObjectsKey]) {
                [managedObjectContext refreshObject:thisSavedManagedObject mergeChanges:YES];
                [managedObjectContext save:nil];
            }
        }
        [notificationUserInfo setObject:savedManagedObjectSet forKey:thisSavedObjectKey];
    }
    // Build a notification suitable for merging changes into MOC.
    NSNotification *saveNotification = [NSNotification notificationWithName:@"" object:nil userInfo:(NSDictionary *)notificationUserInfo];
    [managedObjectContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
                                    withObject:saveNotification
                                 waitUntilDone:YES];
}
Run Code Online (Sandbox Code Playgroud)

Ben*_*man 1

我相信您正在寻找 - (void)refreshObject:(NSManagedObject *)object mergeChanges:(BOOL)flag 。

这将使用持久存储中的信息刷新对象,并根据需要合并更改。