2009-11-29 25 views
8

背景NSDistributedNotificationsを使用してプロセス間でコアデータストアを共有するにはどうすればよいですか?

私はすでにsharing a Core Data store between processesの基礎についての質問を掲載しました。

私は指定された推奨事項を実装しようとしていますが、問題が発生しています。ヘルパーアプリケーションとUI -

私の目標は、

私は、2つのプロセスがあります。どちらも、単一のデータストアを共有します。ヘルパーアプリケーションが新しいデータをストアに保存したときにUIにNSManagedObjectContextを更新するようにします。

現在のプログラムの流れ

  1. ヘルパーアプリケーション・プロセスは、ストアにデータを書き込みます。

  2. ヘルパーアプリケーションでは、NSManagedObjectContextDidSaveNotification通知をリッスンします。

  3. コンテキストが保存されると、そのURI表現とNSArchiverを使用して、挿入、削除、および更新されたオブジェクトをエンコードします。

  4. NSDistributedNotificationCenterに、このエンコードされた辞書をuserInfoとして送信します。

  5. UIプロセスが保存通知をリッスンしています。通知を受け取ると、NSUnarchiverを使用してuserInfoをアーカイブ解除します。

  6. 指定されたURIからすべての更新/挿入/削除されたオブジェクトを検索し、それらをNSManagedObjectsに置き換えます。

  7. 更新/挿入/削除されたオブジェクトでNSNotificationを構築します。

  8. 前の手順で作成したNSNotification Iを渡して、UIプロセスのマネージオブジェクトコンテキストでmergeChangesFromContextDidSaveNotification:を呼び出します。

問題

挿入したオブジェクトは、UI管理オブジェクトコンテキストの罰金に障害が発生していると、彼らはUIに表示されます。この問題は、更新されたオブジェクトに伴い発生します。彼らはただ更新しません。私がしようとするための最も明白なことは UIプロセスにヘルパーアプリケーションプロセスから通知 を保存渡すことであろう

  1. を試してみた何

    。簡単だよね?うーん、ダメ。 分散通知では、userInfo ディクショナリが右の の形式ではないので、私はそれを許可することはできません。 だから私はすべて NSArchivingのことをやっているのです。

  2. 私は refreshObject呼び出して試してみた:mergeChanges:YES にNSManagedObjectsを更新する、 をしかし、これはどの 効果を持っていないようです。メインスレッド上 セレクタと 現在のスレッド:

  3. 私は mergeChangesFromContextDidSaveNotificationを実行しようとしました。いずれの結果も には現れません。

  4. 私は 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]; 
} 
+1

永続ストアファイル自体が更新されるのを見るのではなく、プロセス間通信を使用しようとしている理由はありますか? –

+0

実際にはありません。しかし、私がストアファイルを見た場合、マネージドオブジェクトコンテキストをリフレッシュする何らかの方法が必要であり、これを行うための唯一の方法はmergeChangesFromContextDidSaveNotification:メソッドです。私はこの方法に頼らずにMOCをリフレッシュする本当に明白な方法がないと思う。 –

+0

'for(thisSavedObjectSet allObjectsのid thisSavedObject)'は 'for(id thisSavedObject in thisSavedObjectSet) 'と書くことができます。 – user102008

答えて

1

あなたが探している - (無効)refreshObject:(NSManagedObject *)オブジェクトmergeChanges:(BOOL)フラグI信じる。

これは永続ストア内の情報でオブジェクトを更新し、必要に応じて変更をマージします。

+0

私はこれを自分のコードで使っています。しかし、私はそれを使用している方法で、それは動作していないようです。 –

1

私はMikeの提案に行き、ストアファイルの変更を監視します。

最も効率的ではないかもしれませんが、店舗が変更された場合、2番目のプロセスで- [NSManagedObjectContext reset]を使用して成功しました。私のケースでは、コードはかなりリニアです—私はすべてリセット後にいくつかのデータの取得要求を実行しています。バインディングや複雑なUIではどのように動作するのかわかりませんが、自動的に処理されない場合は手動で更新するように通知することができます。

1

私が取り組んできたiPhoneアプリではまったく同じ問題がありました。私のケースでは、解決策は、コンテキストのstalenessIntervalを適切に無限小(例えば、0.5秒)に設定することを含む。

0

管理対象オブジェクトコンテキストのstalenessIntervalを設定します。私の場合は、プロセスの代わりに複数のスレッドが必要です。

2

私は、すべてのオブジェクトが正しく障害が発生しているが、障害は私が [= 0 MOC stalenessInterval]をしなければならなかったので、まだ更新なし

キャッシュにフェッチされている

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

方法を使用;

そしてそれはついに関係を持って働いた。

+0

stalenessIntervalを設定すると、それは私のためになりました。ありがとう! – MrMage

1

これは、サンドボックスアプリを除いて動作します。ユーザー情報dictで通知を送信することはできません。代わりに、XPCやDOのような他のIPCを検討してください。

システムでビジー状態の場合、NSDustributedNotificationCenterを使用することは必ずしも100%ではありません。

関連する問題