背景
我已经发布了一个关于sharing a Core Data store between processes的基础知识的问题。
我正在尝试实施所提出的建议,但我遇到了问题。
我的目标
我有两个流程 - 帮助应用程序和UI。它们共享一个数据存储。当Helper App将新数据保存到商店时,我希望UI更新它的NSManagedObjectContext。
当前的计划流程
Helper App Process将数据写入商店。
在Helper应用程序中,我侦听NSManagedObjectContextDidSaveNotification通知。
保存上下文后,我使用URI表示和NSArchiver对插入,删除和更新的对象进行编码。
我将NSNotification发送到NSDistributedNotificationCenter,并将此编码字典作为userInfo发送。
UI进程正在侦听保存通知。收到通知后,它会使用NSUnarchiver取消归档userInfo。
它从给定的URI中查找所有更新/插入/删除的对象,并用NSManagedObjects替换它们。
它使用更新/插入/删除的对象构建NSNotification。
我在UI流程的托管对象上下文中调用mergeChangesFromContextDidSaveNotification:传入我在上一步中构建的NSNotification。
问题
插入的对象出现在UI管理对象上下文中,并且它们出现在UI中。问题来自更新的对象。他们只是不更新。
我尝试了什么
最明显的尝试就是 是通过保存通知 从Helper App流程到 UI流程。容易,对吗?好吧,不。 分布式通知不会 允许我以userInfo的身份执行此操作 字典不对 格式。这就是为什么我要做所有的事情 NSArchiving的东西。
我试过打电话 refreshObject:mergeChanges:是的 要更新的NSManagedObjects, 但这似乎没有 效果。
我试过表演了 mergeChangesFromContextDidSaveNotification: 选择器在主线程和 当前线程。似乎都没有 影响结果。
我尝试过使用过 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];
}
}
用户界面代码
-(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];
}
答案 0 :(得分:2)
我使用了
中的方法http://www.mlsite.net/blog/?p=518
然后每个对象都出现故障但是故障是在缓存中获取的,所以仍然没有更新
我必须这样做 [moc stalenessInterval = 0];
它终于有了合作关系。
答案 1 :(得分:1)
你正在寻找 - (void)refreshObject:(NSManagedObject *)对象mergeChanges:(BOOL)标志我相信。
这将使用持久性存储中的信息刷新对象,并根据需要合并更改。
答案 2 :(得分:1)
我会选择迈克的建议,只是看商店文件的变化。
虽然它可能不是最有效的,但是当商店发生变化时,我在第二个流程中使用- [NSManagedObjectContext reset]
成功了。在我的情况下,代码是相当线性的 - 我所做的就是在重置后运行一些数据的获取请求。我不知道这将如何与绑定和复杂的UI一起使用,但如果没有自动处理,您可能会发布通知以手动更新内容。
答案 3 :(得分:1)
我和我一直在研究的iPhone应用程序存在同样的问题。在我的例子中,解决方案涉及将Context的stalenessInterval设置为适当的无穷小(例如,0.5秒)。
答案 4 :(得分:1)
这适用于沙箱应用程序除外。您无法使用用户信息dict发送通知。而是考虑一些其他的IPC,如XPC或DO。
另外,如果系统繁忙,使用NSDustributedNotificationCenter并不总是100%。
答案 5 :(得分:0)
设置托管对象上下文的stalenessInterval有效。我的情况涉及多个线程而不是处理。