背景NSDistributedNotificationsを使用してプロセス間でコアデータストアを共有するにはどうすればよいですか?
私はすでにsharing a Core Data store between processesの基礎についての質問を掲載しました。
私は指定された推奨事項を実装しようとしていますが、問題が発生しています。ヘルパーアプリケーションとUI -
私の目標は、
私は、2つのプロセスがあります。どちらも、単一のデータストアを共有します。ヘルパーアプリケーションが新しいデータをストアに保存したときにUIにNSManagedObjectContextを更新するようにします。
現在のプログラムの流れ
ヘルパーアプリケーション・プロセスは、ストアにデータを書き込みます。
ヘルパーアプリケーションでは、NSManagedObjectContextDidSaveNotification通知をリッスンします。
コンテキストが保存されると、そのURI表現とNSArchiverを使用して、挿入、削除、および更新されたオブジェクトをエンコードします。
NSDistributedNotificationCenterに、このエンコードされた辞書をuserInfoとして送信します。
UIプロセスが保存通知をリッスンしています。通知を受け取ると、NSUnarchiverを使用してuserInfoをアーカイブ解除します。
指定されたURIからすべての更新/挿入/削除されたオブジェクトを検索し、それらをNSManagedObjectsに置き換えます。
更新/挿入/削除されたオブジェクトでNSNotificationを構築します。
前の手順で作成したNSNotification Iを渡して、UIプロセスのマネージオブジェクトコンテキストでmergeChangesFromContextDidSaveNotification:を呼び出します。
問題
挿入したオブジェクトは、UI管理オブジェクトコンテキストの罰金に障害が発生していると、彼らはUIに表示されます。この問題は、更新されたオブジェクトに伴い発生します。彼らはただ更新しません。私がしようとするための最も明白なことは UIプロセスにヘルパーアプリケーションプロセスから通知 を保存渡すことであろう
を試してみた何
。簡単だよね?うーん、ダメ。 分散通知では、userInfo ディクショナリが右の の形式ではないので、私はそれを許可することはできません。 だから私はすべて NSArchivingのことをやっているのです。
私は refreshObject呼び出して試してみた:mergeChanges:YES に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];
}
永続ストアファイル自体が更新されるのを見るのではなく、プロセス間通信を使用しようとしている理由はありますか? –
実際にはありません。しかし、私がストアファイルを見た場合、マネージドオブジェクトコンテキストをリフレッシュする何らかの方法が必要であり、これを行うための唯一の方法はmergeChangesFromContextDidSaveNotification:メソッドです。私はこの方法に頼らずにMOCをリフレッシュする本当に明白な方法がないと思う。 –
'for(thisSavedObjectSet allObjectsのid thisSavedObject)'は 'for(id thisSavedObject in thisSavedObjectSet) 'と書くことができます。 – user102008