Observer le ManagedObjectContext
Bonjour,
Au cours d'un autre sujet, j'ai reçu en fait deux façons de faire qui me semblent se recouper, mais je ne sais pas de quelle manière exactement.
Problème: une unique classe Core Data Desk (Model) possède une représentation DeskView sur l'écran (View). Le modèle ne connaà®t que deux attributs: coordonnées et couleur. La vue qui le représente peut être créée, manipulée, détruite par l'utilisateur. Un ViewController (Controller) gère la connexion entre le modèle et la vue.
Le problème du sujet ci-dessus était d'implémenter l'aspect visuel du Undo/Redo en évitant les retain cycles et les dangling pointers. J'ai utilisé les patterns suivants:
Model --> Notifications --> Controller <-- Delegation <-- View
... ça marche, on peut voyager dans l'historique des modifications (toutes sans exception) dans un sens (undo) comme dans l'autre (redo) sans le moindre message d'erreur.
La solution de jpimbert
Il faut définir la méthode awakeFromSnapshotEvents: sur les objets gérés, elle sera appelée avec NSSnapshotEventUndoDeletion lorsque l'objet sera recréé. C'est le bon endroit pour lancer la reconstruction de la vue de cet objet, par exemple par une notification.
était suffisante, et je l'ai adoptée, mais ensuite une intéressante discussion a démarré sur la pertinence et les limites du MVC, et Ali m'a, en gros, signalé que je réinventais la roue, le MOC me fournissant tout ce dont j'avais besoin à l'aide des notifications intégrées.
Or, cela semble tellement évident qu'à part un entrefilet dans la doc, je n'ai pas trouvé d'exemple probant de ce mécanisme, à part des tas de posts sur le problème du multithreading (le MOC n'est pas thread-safe, du coup on crée d'autres MOC privés et on merge le tout.)
Je n'ai qu'un MOC et je ne lance pas de threads maison. Mon problème est donc assez simple: la solution de jpimbert peut-elle être généralisée dans celle citée par Ali, et si oui comment?
jpimbert fournit une solution ponctuelle et opérationnelle: mon unique classe signale qu'elle a été l'objet d'un undo/redo.
Ali m'oriente vers le mécanisme intégré: le MOC balance une notification à chaque changement du modèle, quelle que soit l'entité concernée. Le userInfo de la notification est un NSDictionary qui contient trois clé: inserted, deleted et updated. Ces clés ont chacune pour valeur une NSArray contenant les objets modifiés.
Question: comment éviter de "réinventer la roue"? A part me faire tancer, je n'ai pas reçu de réponse claire. Dois-je parser tout le dictionnaire de la notification pour voir s'il contient l'un des objets Desk? Et si oui, comment obtenir le type de modification (le NSSnapshotEventType) dont j'ai besoin pour ressusciter, renvoyer ad patres ou ramener à sa position antérieure ma DeskView?
D'avance merci.
Réponses
Je ne vois pas trop le problème.
Core Data prévoit deux mécanismes de reporting des modifications :
- au niveau de chaque classe, par appel direct d'une méthode de la classe
- globalement au niveau du contexte, par notifications
On peut ajouter que lorsqu'on utilise un NSFetchedResultsController, les notifications du contexte sont "digérées" par le contrôleur de résultats qui va appeler des méthodes de son délégué, généralement un Contrôleur de vue en table.
Tu as ces trois mécanismes à ta disposition qui seront plus ou moins opportuns selon les cas.
Il te suffit de choisir le plus approprié pour respecter le principe KISS. Dans aucun des cas tu ne réinventes la roue puisque tu utilise un mécanisme existant.
Si tu ne t'intéresses qu'aux modifications sur un seul type d'entité, la première solution me paraà®t très bien.
Une alternative serait de rechercher tes entités Desk avec un NSFetchedResultsController pour que son délégué soit informé des apparitions/disparitions de l'une de ces entités.