背景
我已经发布了一个关于
sharing a Core Data store between processes
.
我正在尝试执行给出的建议,但遇到了一些问题。
我的目标
我有两个进程-助手应用程序和用户界面。它们都共享一个数据存储。当助手应用程序将新数据保存到存储时,我希望用户界面更新它的nsmanagedObjectContext。
当前程序流
-
Helper应用程序进程将数据写入存储。
-
在Helper应用程序中,我监听nsManagedObjectContextDidSaveNotification通知。
-
在保存上下文时,我使用插入的、删除的和更新的对象的URI表示和nsarchiver对它们进行编码。
-
我向nsdistributednotificationcenter发送一个nsnotification,使用这个编码的字典作为用户信息。
-
UI进程正在侦听保存通知。当它收到通知时,它会使用nsonarchiver取消用户信息的归档。
-
它从给定的URI中查找所有更新/插入/删除的对象,并将其替换为nsmanagedObjects。
-
它使用更新/插入/删除的对象构造一个nsnotification。
-
我调用MergeChangesFromContextDidSaveNotification:在UI进程的托管对象上下文中,传递在上一步中构造的NSNotification。
问题
插入的对象在UI管理的对象上下文fine中出错,它们出现在UI中。更新的对象会出现问题。他们只是不更新。
我试过什么
-
最明显的尝试是
通过保存通知
从Helper应用程序进程到
UI过程。容易,对吧?嗯,不。
分布式通知不会
允许我作为用户信息执行此操作
字典不在右边
格式。所以我才这么做
无存档的东西。
-
我试过打电话
刷新对象:合并更改:是打开
要更新的nsmanagedObjects,
但是这个好像没有
效果。
-
我试过表演
从ContextDidSaveNotification合并更改:
主线程上的选择器和
当前线程。两者似乎都不是
影响结果。
-
我试过用
从ContextDidSaveNotification合并更改:
在线程之间之前,哪一个
课程简单多了,而且很有效
完美。但我也需要这个
流程之间的功能。
选择?
我是不是错过了什么?我一直觉得我让它比需要的要复杂得多,但是在阅读了文档几次并花了几天时间之后,我看不到任何其他刷新用户界面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];
}
}
用户界面代码
-(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];
}