背景如何在使用NSDistributedNotifications的進程之間共享Core Data存儲?
我已經發布了關於sharing a Core Data store between processes基本問題。
我試圖執行給出的建議,我遇到了問題。
我的目標
我有兩個進程 - 的助手應用程序和用戶界面。他們都共享一個數據存儲。當輔助應用程序將新數據保存到商店時,我希望UI更新它的NSManagedObjectContext。
當前程序流
的助手應用程序過程將數據寫入存儲。
在助手應用程序中,我偵聽NSManagedObjectContextDidSaveNotification通知。
保存上下文時,我使用它們的URI表示和NSArchiver對插入,刪除和更新的對象進行編碼。
我發送一個NSNotification到NSDistributedNotificationCenter並將此編碼字典作爲userInfo。
UI進程正在偵聽保存通知。當它收到通知時,它使用NSUnarchiver解除對userInfo的存檔。
它從給出的URI中查找所有更新/插入/刪除的對象,並用NSManagedObjects替換它們。
它使用更新/插入/刪除的對象構造NSNotification。
我調用mergeChangesFromContextDidSaveNotification:在UI進程的託管對象上下文中傳入我在上一步中構造的NSNotification。
的問題
插入的對象是有故障的入UI管理對象上下文精細和它們出現在UI。問題伴隨更新的對象。他們只是不更新。
我已經試過
最明顯的事情,試圖將 是通過從助手應用程序過程中的保存通知 到 UI過程。很簡單,對吧?那麼,不。 分佈式通知不會 允許我這樣做,因爲userInfo 字典不是正確的 格式。這就是爲什麼我正在做所有的NSArchiving的東西。
我已經打過電話 refreshObject:mergeChanges:是對 的NSManagedObjects更新, 但這似乎並沒有什麼效果 。
我已經試過執行 mergeChangesFromContextDidSaveNotification:在主線程 選擇和 當前線程。似乎 影響結果。
我使用 mergeChangesFromContextDidSaveNotification嘗試: 之前線程之間,其中 當然要簡單得多,它完美地工作 。但是我需要在進程之間提供相同的功能 。
替代品?
我在這裏錯過了什麼嗎?我一直都覺得自己做得比想要的要複雜得多,但是在多次閱讀文檔並花了幾天時間之後,我看不到任何其他方式來刷新MOC UI。
有沒有更好的方法來做到這一點?或者我在代碼中的某個地方犯了一個愚蠢的錯誤?
守則
我試圖使它儘可能地易讀,但它仍然是一個爛攤子。抱歉。
助手應用程序代碼
-(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代碼
-(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];
}
是否有一個原因,你試圖使用進程間通信,而不是看持久存儲文件本身來查看它何時更新? –
不是。但是,如果我看了商店文件,我需要刷新Managed Object Context的一些方法,我可以通過mergeChangesFromContextDidSaveNotification:方法找到執行此操作的唯一方法。我懷疑我錯過了一個非常明顯的刷新MOC而不依賴這種方法的方式。 –
'for(id thisSavedObject in [thisSavedObjectSet allObjects])''可以寫成for(id thisSavedObject in thisSavedObjectSet)' – user102008