4

Je n'arrive pas à faire en sorte que mon interface utilisateur reflète les modifications externes (apportées par un autre processus) à un magasin de données sqlite.Problème de réinitialisation/actualisation NSManagedObjectContext et NSArrayController

J'ai une vue NSArrayController/table basée sur des données de base assez standard. Mon application est notifié que les changements externes ont été apportées aux données, à quel point je fais un

[managedObjectContext reset]; // brute force, but data set is small 

Le problème est, cette opération efface toutes les données de la table. Le fichier arrangedObjects du contrôleur de réseau est également vide. Je pensais qu'un ultérieur

[arrayController fetch:nil]; 

pourrait aider, mais ce n'est pas le cas. L'exécution d'une requête d'extraction sur le managedObjectContext montre que les données sont présentes et mises à jour, ainsi le managedObjectContext connaît les modifications.

Des indices sur la façon de "récupérer" à partir de la réinitialisation? Ou peut-être l'approche de réinitialisation est-elle complètement erronée, auquel cas existe-t-il un meilleur moyen de charger les changements externes?

+0

Lorsque vous dites un autre processus, est-il externe à l'application ou à un autre thread dans l'application? –

+0

Je veux dire processus dans le sens habituel, donc oui - c'est externe à l'application, pas seulement un fil séparé dans l'application. – Adrian

Répondre

1

Je ne pense pas que deux processus soient supposés fonctionner dans la même base de données Core Data. Il est probablement préférable de laisser un processus agir comme un serveur qui possède (et ouvre) la base de données et laisser l'autre lui envoyer des commandes pour apporter des modifications. Je ne pense pas que Core Data ait jamais été conçu pour prendre en charge plusieurs processus parlant à la même base de données.

+1

C'est correct. Core Data gère les magasins atomiques et ne peut pas être utilisé comme une base de données client-serveur. –

+0

Oui, maintenant que j'ai refactorisé d'avoir le même processus - et en fait le même fil - fonctionnant toujours sur la base de données, les choses fonctionnent bien. Malheureusement, vu que la base de données Sqlite sous-jacente gère l'accès et la manipulation multi-processus. Il semble raisonnable de s'attendre à ce que Core Data soit en mesure de se mettre à jour à partir de la base de données lorsqu'il en est informé. – Adrian

0

Donc, j'ai joué avec cette situation exacte, et je ne vais pas contredire la première réponse - vous n'êtes probablement pas censé faire cela, et si vous devez, peut-être iCloud fonctionne. N'utilisez pas ce code. Je l'ai fourni pour aider les autres à découvrir tous les problèmes que je n'ai pas résolus et à passer à autre chose.

Cela dit, vous pouvez faire ce que la question initiale cherchait à forcer le contrôleur do-- de recharger à partir du disque:

// Tear down bindings and context, create new context & rebind 
[self.watcherAC unbind:@"managedObjectContext"]; 
[self saveAction:self]; // Optional, dependent on NSMergePolicy, etc 
self.managedObjectContext = [[NSManagedObjectContext alloc] init]; 
self.managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy; 
[self.managedObjectContext setPersistentStoreCoordinator:self.persistentStoreCoordinator]; 
[self.watcherAC bind:@"managedObjectContext" toObject:self withKeyPath:@"managedObjectContext" options:nil]; 

// Force controller to refetch and rearrange 
NSError* error; 
[self.watcherAC fetchWithRequest:nil merge:NO error:&error]; // Immediate fetch 
[self.watcherAC prepareContent]; 
[self.watcherAC rearrangeObjects]; 

qui rafraîchit du magasin sur le disque du contenu du tableView. (Le tableauView est lié au contrôleur array watcherAC)

J'ai trouvé que fetch: n'est pas immédiat - c'est fait la prochaine fois par la boucle d'exécution pour l'application. Donc, pour avoir Fetch/réorganiser fait dans l'ordre, vous devez utiliser fetchWithRequest:

Je ne suis pas sûr prepareContent: est nécessaire, même si elle peut avoir contribué à effacer les défauts dans le contenu du contrôleur.

Je n'ai pas pu l'obtenir pour restaurer la sélection tableView, bien que cela puisse être parce que je le fais dans un appel de délégué tableview, donc la sélection de la vue est désynchronisée avec la sélection du contrôleur. . Peut-être cela pourrait fonctionner pour quelqu'un, mais je suggère d'essayer de comprendre comment ne pas allouer un nouveau MOC une fois que votre vue a des liaisons à elle.

Questions connexes