首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用NSDistributedNotifications在进程之间共享核心数据存储?

如何使用NSDistributedNotifications在进程之间共享核心数据存储?
EN

Stack Overflow用户
提问于 2009-11-29 13:17:35
回答 7查看 2.6K关注 0票数 8

背景

我已经发布了一个关于sharing a Core Data store between processes基础知识的问题。

我正在努力执行所给的建议,但我遇到了一些问题。

我的目标

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

当前程序流

  1. Helper进程将数据写入商店。在Helper中的
  2. 中,我侦听NSManagedObjectContextDidSaveNotification通知。在保存上下文时,我使用其URI表示对插入、删除和更新的对象进行编码,NSArchiver.
  3. I使用此编码字典向NSDistributedNotificationCenter发送一个NSNotification,因为userInfo.
  4. The UI进程正在侦听保存通知。当它收到通知时,它使用NSUnarchiver.
  5. It从UI中查找所有更新/插入/删除对象,并用NSManagedObjects.
  6. It替换它们,用更新/插入/删除对象来构造NSNotification。

问题

插入的对象在UI托管对象上下文中发生故障,并且它们出现在UI中。问题在于更新的对象。他们只是不更新。

我试过什么

  1. 最明显的尝试是将保存通知从Helper进程传递到UI进程。别紧张,对吧?嗯,不是。分布式通知不允许我这样做,因为userInfo字典格式不正确。这就是为什么我要做所有的NSArchiving工作。
  2. 我试着调用刷新对象:mergeChanges:是的,在要更新的NSManagedObjects上,但是这似乎没有任何效果。
  3. ,我尝试在主线程和当前线程上执行mergeChangesFromContextDidSaveNotification:选择器。
  4. 我尝试过在线程之间使用mergeChangesFromContextDidSaveNotification:‘ve,这当然要简单得多,而且工作得非常完美。但是,我需要在进程之间使用相同的功能。

Alternatives?

我是不是漏掉了什么?我一直觉得这比需要的复杂得多,但在阅读了几次文档并花了几天时间之后,我看不到任何其他方法来刷新UI的MOC。

有什么更优雅的方法吗?还是我只是在代码中犯了一个愚蠢的错误?

代码

我试着使它尽可能的可读性,但它仍然是一团糟。抱歉的。

助手应用程序代码

代码语言:javascript
复制
   -(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];
        }
    }

UI代码

代码语言:javascript
复制
-(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];
}
EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2009-12-10 19:13:50

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

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

票数 1
EN

Stack Overflow用户

发布于 2011-01-28 16:31:51

我用了这个方法

http://www.mlsite.net/blog/?p=518

那么每一个对象都是正确的错误,但是这些错误都是在缓存中获取的,所以仍然没有更新。

我不得不做moc stalenessInterval = 0;

它终于起作用了,有了关系。

票数 2
EN

Stack Overflow用户

发布于 2009-12-13 15:38:57

我会同意迈克的建议,看看商店的文件是否有变化。

虽然它可能不是最有效的,但我在第二个过程中成功地使用了- [NSManagedObjectContext reset],当商店发生更改时。在我的例子中,代码是相当线性的--我所做的就是在重置后对某些数据运行一个获取请求。我不知道绑定和复杂的UI将如何工作,但是如果不自动处理,您可能可以发布一个通知来手动更新。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1815518

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档