8
votes

Comment partager un magasin de données de base entre les processus à l'aide de NSDistribuButednotifications?

fond strong>

J'ai déjà posté une question sur les bases de Partage d'un magasin de données de base entre les processus . P>

J'essaie de mettre en œuvre les recommandations données et je cours dans les problèmes. P>

mon objectif strong> p>

J'ai deux processus - l'application Helper et l'interface utilisateur. Ils partagent tous les deux un seul magasin de données. Je souhaite que l'interface utilisateur à mettre à jour est NsmaniedObjectContext lorsque l'application Helper a enregistré de nouvelles données dans le magasin. P>

flux de programme actuel fort> P>

  1. Le processus d'application d'assistance écrit des données au magasin. P> li>

  2. Dans l'application Helper, j'écoute pour NsmanieDObjectContextExtDididSavenotification. p> li>

  3. Lorsque le contexte est enregistré, j'encore les objets insérés, supprimés et mis à jour à l'aide de leurs représentations URI et de NSARCHIVER. P> LI>

  4. J'envoie une NSnotification au NSDistribuButednotificationCenter avec ce dictionnaire codé comme utilisateurInfo. P> Li>

  5. Le processus d'interface utilisateur est écoutant pour la notification de sauvegarde. Lorsqu'il reçoit la notification, il aborde l'utilisateurInfo à l'aide de Nsunarchiver. P> Li>

  6. Il lève tous les objets mis à jour / inséré / supprimé de l'URIS donnée et remplace-leur avec NsManageDObjects. P> LI>

  7. Il construit une NSNotification avec les objets mis à jour / inséré / supprimé. P> li>

  8. i appelez mergechangesfromContextDidSacAntification: sur le contexte de l'objet géré du processus d'assurance-chômage, passant dans la NSnotification que j'ai construite à l'étape précédente. P> Li> ol>

    Le problème strong> p>

    Les objets insérés sont défaillants dans le contexte d'objet géré de l'UI et ils apparaissent dans l'interface utilisateur. Le problème vient avec des objets mis à jour. Ils ne mettent tout simplement pas à jour. P>

    ce que j'ai essayé fort> p>

    1. la chose la plus évidente à essayer serait être de transmettre la notification de sauvegarde du processus d'application de l'aide au Processus d'assurance-emploi. Facile, non? Et bien non. Les notifications distribuées ne vont pas Permettez-moi de le faire comme UserInfo Dictionnaire n'est pas dans la droite format. C'est pourquoi je fais tout le Nsarchiving Stuff. P> Li>

    2. J'ai essayé d'appeler Rafraîchir: Mergechanganes: Oui sur NsmanagedObjects à mettre à jour, Mais cela ne semble pas avoir effet. p> li>

    3. J'ai essayé de jouer le MERGECHANGESFROMCONTEXTDIVENTATIFICATION: sélecteur sur le fil principal et le fil de courant. Ni semble affecter le résultat. P> li>

    4. J'ai essayé d'utiliser MERGECHANGESFROMCONTEXTDIVENTATIFICATION: avant entre les threads, lequel de le cours est beaucoup plus simple et ça a fonctionné à la perfection. Mais j'ai besoin de cela même fonctionnalité entre les processus. P> li> ol>

      Alternatives? strong> p>

      suis-ce que je manque quelque chose ici? Je reçois toujours le sentiment que je rendant cela beaucoup plus complexe qu'il n'a besoin que, mais après avoir lu la documentation à plusieurs reprises et passer quelques jours solides à ce sujet, je ne vois aucune autre façon de rafraîchir le MOC de L'UI. P>

      Y a-t-il un moyen plus élégant de faire cela? Ou est-ce que je fais juste une erreur stupide quelque part dans mon code? P>

      le code strong> p>

      J'ai essayé de le rendre lisible que possible, mais c'est toujours un gâchis. Désolé. P>

      Code de l'application fort> p> xxx pré>

      code d'interface utilisateur strong> p>

      -(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];
      }
      


4 commentaires

Y a-t-il une raison pour laquelle vous essayez d'utiliser une communication inter-processus plutôt que de regarder le fichier de magasin persistant lui-même pour voir quand il est mis à jour?


Pas vraiment. Mais si j'ai regardé le fichier de magasin, je devrais avoir un moyen de rafraîchir le contexte de l'objet géré et que je ne peux trouver que pour le faire, c'est par la MergechangesFromContextDididSacovation: méthode. Je soupçonne que je manque un moyen vraiment évident de rafraîchir le MOC sans s'appuyer sur cette méthode.


pour (ID ThiSavedObject dans [ThiSavedObjectSet Allobjects]) pourrait être écrit comme pour (ID ThiSavedObject dans ThiSavedObjectSet)


Ouais, bon point. De retour dans les jours d'héritage du 09 novembre, je n'ai pas réalisé que l'énumération rapide a également fonctionné pour des ensembles.


6 Réponses :


1
votes

Vous recherchez - (vide) RegardObject: (NsmanagedObject *) Objet Mergechanges: (Bool) Drapeau Je crois.

Cela rafraîchira l'objet avec les informations dans le magasin persistant, fusionnant des modifications si vous le souhaitez.


1 commentaires

J'ai utilisé cela dans mon code. Cependant, dans la manière dont je l'utilise, cela ne semble pas fonctionner.



1
votes

J'irais avec la suggestion de Mike et regarder le fichier de magasin pour les modifications.

Bien que ce ne soit peut-être pas le plus efficace, j'ai eu le succès à l'aide de - [nsmaniedObjectContext réinitialiser] à partir d'un deuxième processus lorsqu'il y a un changement dans un magasin. Dans mon cas, le code est assez linéaire - tout ce que je fais est d'exécuter une demande de récupération pour certaines données après réinitialisation. Je ne sais pas comment cela fonctionnera avec des liaisons et une interface utilisateur compliquée, mais vous pourrez peut-être poster une notification pour mettre à jour manuellement les choses si cela n'est pas traité automatiquement.


0 commentaires

1
votes

J'ai eu exactement le même problème avec une application iPhone que je travaille sur. Dans mon cas, la solution consistait à définir la stalespace du contexte à quelque chose de convenablement infinitésimal (par exemple, 0,5 seconde).


0 commentaires

0
votes

Réglage de la stalitéInterval du contexte d'objet géré fonctionne. Mon cas implique plusieurs threads au lieu de processus.


0 commentaires

2
votes

J'ai utilisé la méthode dans

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

Ensuite, chaque objet est correctement défaillant mais les défauts sont récupérables dans le cache, donc toujours aucune mise à jour

je devais faire [Moc StalenessInval = 0];

Et il a finalement travaillé, avec relation.


1 commentaires

Réglage de la stalitéInterval l'a fait pour moi. Merci!



1
votes

Cela fonctionne, à l'exception des applications de sandboxes. Vous ne pouvez pas envoyer de notification avec une info d'utilisateur dict. Considérez plutôt un autre IPC comme XPC ou faire.

sur une note latérale, l'utilisation de NSDustributednotificationCenter n'est pas toujours à 100% si le système est occupé.


0 commentaires