MVC, KVO, KVC & Delegate

SethySethy Membre
janvier 2013 modifié dans Objective-C, Swift, C, C++ #1
Bonjour à  tous,



Après une petite pause, je m'attaque à  ma seconde application. Pour la première, disons que je suis parti du principe que tous les coups étaient permis (je sais, je sais, pas bien).



Cette fois au contraire, je veux absolument profiter de cette appli pour maitriser tout les standards (enfin, un maximum).



J'ai évidemment un souci, mais avant de balancer un bon paquet de lignes de code, j'aimerais que vous validiez l'approche que j'ai choisie.



Objectif : Le controller doit modifier le model qui informera le controller de la modification.



Dans le model :

- Je défini une classe dont les membres sont accessibles via KVC.

- Je crée un observer sur un de ces membres.

- Je crée un protocol delegate qui sera appelé par ma classe model et implémentée dans ma classe controller



Dans le controller :

- J'implémente la fonction required de mon delegate

- Je crée un objet de la classe model

- Je modifie la valeur observée en l'appelant à  l'aide d'un setvalue: forkey:



La séquence devrait être :

- modification de la valeur observée avec le setvalue

- l'observer (enfin la fonction) est appelée

- dans cette fonction j'appelle la méthode du protocol delegate

- cette méthode agit à  son tour dans le controller .



Est-ce que j'ai bon ?



D'avance merci.



Sethy

Réponses

  • J'ai trouvé le petit bug dans mon implémentation, mais n'hésitez pas à  commenter la logique que j'ai choisie.



    Sethy
  • J'ai peur de mal comprendre. Est-ce que c'est le modèle qui s'observe lui-même ?
  • CéroceCéroce Membre, Modérateur
    janvier 2013 modifié #4
    'Sethy' a écrit:


    Objectif : Le controller doit modifier le model qui informera le controller de la modification.


    L'objectif ne me semble déjà  pas très clair :-)

    Je suis d'accord sur le fait que c'est le contrôleur qui va prendre l'initiative de mettre à  jour le modèle (en général).



    Ensuite, est-ce que la mise à  jour du modèle est asynchrone ?



    Si elle est synchrone, alors ça ne sert à  rien, puisque le contrôleur sait que le modèle va être mis à  jour, il n'a qu'à  rafraà®chir les vues à  la suite.



    Si la mà j du modèle est asynchrone, il existe plusieurs manières de procéder. Tu peux utiliser soit la délégation (le modèle prévient le contrôleur quand il est à  jour), soit la KVO (le contrôleur observe les modifications du modèle), mais pas les deux.



    Sous iOS, ou du moins sur iPhone, le KVO a moins d'intérêt que sur Mac, parce que les données s'affichent souvent à  un seul endroit. Le KVO est difficile à  mettre au point parce qu'il faut commencer à  observer et arrêter d'observer aux bons moments, c'est pourquoi la délégation est souvent préférée. Elle a aussi l'avantage d'être plus formelle, ce qui clarifie la structure de l'appli.
  • SethySethy Membre
    janvier 2013 modifié #5
    'yoann' a écrit:


    J'ai peur de mal comprendre. Est-ce que c'est le modèle qui s'observe lui-même ?




    En fait, oui.



    Je crois que ta remarque me fait comprendre mon erreur.
  • 'Sethy' a écrit:


    En fait, oui.



    Je crois que ta remarque me fait comprendre mon erreur.




    Remplace ton système de modèle qui s'observe lui même par des accesseurs implémenté à  la main à  la place des @property automatique pour savoir quand une valeur va changer. C'est moins gourmand en ressources.



    Ensuite réfléchit bien a ton système, ça me semble bizarre d'avoir un delegate sur un modèle.



    Généralement on utilise plus des notifications pour les changement du coté du modèle et une observation du contrôleur sur le modèle si besoin.
  • SethySethy Membre
    janvier 2013 modifié #7
    'Céroce' a écrit:


    L'objectif ne me semble déjà  pas très clair :-)

    Je suis d'accord sur le fait que c'est le contrôleur qui va prendre l'initiative de mettre à  jour le modèle (en général).



    Ensuite, est-ce que la mise à  jour du modèle est asynchrone ?



    Si elle est synchrone, alors ça ne sert à  rien, puisque le contrôleur sait que le modèle va être mis à  jour, il n'a qu'à  rafraà®chir les vues à  la suite.



    Si la mà j du modèle est asynchrone, il existe plusieurs manières de procéder. Tu peux utiliser soit la délégation (le modèle prévient le contrôleur quand il est à  jour), soit la KVO (le contrôleur observe les modifications du modèle), mais pas les deux.



    Sous iOS, ou du moins sur iPhone, le KVO a moins d'intérêt que sur Mac, parce que les données s'affichent souvent à  un seul endroit. Le KVO est difficile à  mettre au point parce qu'il faut commencer à  observer et arrêter d'observer aux bons moments, c'est pourquoi la délégation est souvent préférée. Elle a aussi l'avantage d'être plus formelle, ce qui clarifie la structure de l'appli.




    Je crois que j'ai fait dans l'usine à  gaz image/wink.png' class='bbc_emoticon' alt=';)' />



    Comme je l'avais expliqué, j'essaie de faire du canonique (en ce compris le sens canon-ique).



    J'ai quand même une question. Imaginons 2 viewcontrollers différents qui peuvent tout deux modifier la même valeur dans le model. Avec mon système usine à  gaz, je peux informer les 2 views controllers "automatiquement". Si je laisse cette tâche à  un viewcontroller, il doit informer l'autre de la modif ?



    Je pense par exemple à  une appli de type "tabbed', avec dans une même info présente dans 2 tabs.
  • 'yoann' a écrit:


    Remplace ton système de modèle qui s'observe lui même par des accesseurs implémenté à  la main à  la place des @property automatique pour savoir quand une valeur va changer. C'est moins gourmand en ressources.



    Ensuite réfléchit bien a ton système, ça me semble bizarre d'avoir un delegate sur un modèle.



    Généralement on utilise plus des notifications pour les changement du coté du modèle et une observation du contrôleur sur le modèle si besoin.




    Je crois que je comprends mieux. Je vais essayer d'appliquer ça à  mon exemple.
  • CéroceCéroce Membre, Modérateur
    'Sethy' a écrit:


    Avec mon système usine à  gaz, je peux informer les 2 views controllers "automatiquement". Si je laisse cette tâche à  un viewcontroller, il doit informer l'autre de la modif ?


    Non, c'est une très mauvaise idée parce que ça implique que les deux view controllers se connaissent, on créerait donc une dépendance.

    On pourrait concevoir un système qui ferait que le Modèle prévienne une liste de destinataires, mais ça me semble peu nécessaire à  cause de la réponse suivante...


    'Sethy' a écrit:


    Je pense par exemple à  une appli de type "tabbed', avec dans une même info présente dans 2 tabs.


    Si tu y réfléchis, seul le view controller courant a besoin d'être informé des modifs du modèle. L'autre VC peut se mettre à  jour dans viewWillAppear.



    Effectivement, c'est un cas où utiliser la KVO devient intéressant. Cependant toujours avec la Délégation, on pourrait avoir un troisième objet qui est le délégué du modèle, qui se conforme au protocole UITabBarControllerDelegate, et qui prévient le controller courant d'une mà j.



    Ce que j'insinue est qu'il n'y a pas de solution universelle; mais à  vrai dire, si je devais faire cela, j'utiliserais probablement la KVO.
  • Si on prends l'exemple de deux Vues (Va et Vb) avec les contrôleurs associés (Ca et Cb) et un seul modèle (M) (qui comprend également le service d'accès aux données).



    Si Va est une vue master et Vb une vue détail qui prends en compte les changement en temps réel, l'utilisateur peut éditer le titre de l'élément affiché par Vb et donc Va doit se mettre à  jour.



    Pour que Va reste à  jour il faut que Ca observe la clef titre de l'entité provenant de M et représentant l'objet sélectionné. Quand la notification de changement est reçu par Ca il s'occupera de mettre à  jour Va.



    C'est simpliste et ne prends pas en compte d'éventuels questions de performances et d'implémentation mais ça n'utilise que le KVO standard, rien à  faire du coté de M sinon respecter les conventions d'accesseurs.
Connectez-vous ou Inscrivez-vous pour répondre.