3

J'ai quelques problèmes avec NSFetchedResultsController et CoreData, dont je serais très reconnaissant d'obtenir de l'aide.Gestion des changements d'arrière-plan avec NSFetchedResultsController

Problème 1 - Mises à jour: je mets à jour mon magasin sur un thread d'arrière-plan qui entraîne la suppression, l'insertion ou la mise à jour de certaines lignes. Les modifications sont fusionnées dans le contexte du thread principal à l'aide de la méthode "mergeChangesFromContextDidSaveNotification:". Les insertions et les suppressions sont mises à jour correctement, mais pas les mises à jour (par exemple, l'étiquette de cellule n'est pas mise à jour avec le changement) bien que j'ai confirmé les mises à jour à venir par contextDidSaveNotifcation, exactement comme les insertions et supprimé. Ma solution de contournement actuelle est de changer temporairement l'intervalle de stabilité du contexte à 0, mais cela ne semble pas être la solution idéale.

Problème 2 - Suppression d'objets: ma taille de lot de récupération est de 20. Si un objet est supprimé par le thread d'arrière-plan qui se trouve dans les 20 premières lignes, tout fonctionne correctement. Mais si l'objet est après les 20 premières lignes et que la table est défilée, une erreur "CoreData ne peut pas remplir une faute" est déclenchée. J'ai essayé de rétablir le contexte et de réécrire le fetch fetch - tout en vain. Remarque: Dans ce scénario, la méthode de délégué frc "didChangeObject ...." n'est pas appelée pour la suppression. Je suppose que c'est parce que l'objet en question n'avait pas été bloqué à ce moment (car il se trouvait en dehors de la plage d'exploration initiale). Mais pour une raison quelconque, le contexte pense toujours que l'objet est autour, bien qu'il ait été supprimé du magasin.

Édition 3 - Suppression de sections: Lorsque la suppression d'une ligne entraîne la suppression d'une section, j'ai obtenu le "nombre de lignes invalide dans la section ???" Erreur. J'ai travaillé autour de cela en supprimant la ligne "reloadSection" de la section NSFetchedResultsChangeMove: et en la remplaçant par "[tableView insertRowsAtIndexPaths ...." Cela semble fonctionner, mais encore une fois, je ne suis pas sûr si c'est la meilleure solution.

Toute aide serait grandement appréciée. Je vous remercie!

Répondre

10

Je pense que tous vos problèmes sont liés au cache du contrôleur de résultats récupérés.

Le problème 1 est dû à la FRC utilisant les objets mis en cache (dont les ID n'ont pas changé). Lorsque vous ajoutez ou supprimez un objet qui modifie les ID et force une mise à jour du cache t le faire de manière fiable.

Le problème 2 est dû au contrôle FRC de l'objet dans le cache. Très probablement, l'objet a une relation non protégée qui persiste dans le cache. Lorsque vous le supprimez en arrière-plan, la fonction FRC tente de provoquer une erreur dans l'objet à l'autre extrémité de la relation et ne peut pas le faire.

Problème 3: Même problème. Le cache ne reflète pas les modifications.

Vous ne devriez pas utiliser le cache d'un FRC lorsqu'un objet autre que le FRC modifie le modèle de données. Vous avez deux options:

  1. (Préféré) N'utilisez pas le cache. Lors de la création de la FRC, définissez la propriété de cache sur zéro.
  2. Efface le cache chaque fois que le processus d'arrière-plan modifie le modèle de données.

Bien sûr, deux défaites dans le but d'utiliser le cache en premier lieu.

Le cache n'est utile que si les données sont en grande partie statiques et/ou si la FRC gère les modifications. Dans toute autre circonstance, vous ne devez pas l'utiliser car FRC doit vérifier le modèle de données réel de manière répétée pour s'assurer qu'il comprend bien les données.Il ne peut pas compter sur les copies d'objet qu'il a écrasées parce qu'une autre entrée peut avoir changé les objets réels.

+0

Merci beaucoup. En effet, le cache a été responsable de beaucoup de mes malheurs. Il ne me reste plus qu'un seul problème: lorsque je sauvegarde le contexte après une suppression synchronisée depuis le contexte d'arrière-plan, un NSFetchedResultsChangeInsert frc est appelé et le contact supprimé est réinséré, malgré la stratégie de fusion NSRollbackMergePolicy. – RunLoop

+0

Ne pas définir l'intervalle de stabilité à 0 résout le problème décrit dans le commentaire ci-dessus, mais cela entraîne à nouveau des modifications de mise à jour, par ex. le nom de l'étiquette de la cellule change, n'étant pas reflété. – RunLoop

+0

Le dernier problème était en quelque sorte lié au fait que j'utilisais un coordinateur de magasin persistant séparé pour le moc en arrière-plan. L'utilisation du fichier psc principal en conjonction avec le fait de ne pas utiliser un cache a résolu tous les problèmes. – RunLoop

0

Mon conseil:

  • détecter les changements nécessaires sur le fil de fond
  • afficherons les changements au fil conducteur comme une charge utile
  • Effectuez les modifications réelles et d'économiser sur le thread principal (objet géré Contexte sur le thread principal)
  • Utilisez le cache pour le FRC; vous obtiendrez de meilleures performances
  • Citation de "Pro Core Data pour iOS" par Michael Privat, Robert Warner:

    « Core Data gère ses caches intelligemment de sorte que si les résultats sont mis à jour par un autre appel, le cache est supprimé s'il est affecté. "