Méthodes dynamiques en fonctions des properties
Pyroh
Membre
Bonjour à tous je travaille activement en ce moment et j'aimerai bien palier à quelques manques de NSObject notamment au niveau du KVO et des NSUndoManager.
Je me heurte à un soucis que je peux régler avec beaucoup de code ou une astuce. Je préfère l'astuce parce que ça me paraà®t beaucoup plus intéressant.
Quand on code une classe sur Xcode on se retrouve avec des méthodes du type :
J'aimerai savoir comment faire une telle chose. Le soucis c'est que je ne sais pas quoi chercher je me doute que ça a un rapport avec le Runtime mais la doc est touffue et je ne sais pas exactement ce que je cherche.
Donc si quelqu'un a une piste sur le sujet ça m'aiderai beaucoup. Après je mènerai des tests et je partagerai mon travail si le résultat est concluant (j'aurai une bonne raison de découvrir cocoapods)
Je me heurte à un soucis que je peux régler avec beaucoup de code ou une astuce. Je préfère l'astuce parce que ça me paraà®t beaucoup plus intéressant.
Quand on code une classe sur Xcode on se retrouve avec des méthodes du type :
+ (NSSet *)keyPathsForValuesAffectingC'est très pratique et l'existence de ces méthodes est fonction des properties de la classe.
J'aimerai savoir comment faire une telle chose. Le soucis c'est que je ne sais pas quoi chercher je me doute que ça a un rapport avec le Runtime mais la doc est touffue et je ne sais pas exactement ce que je cherche.
Donc si quelqu'un a une piste sur le sujet ça m'aiderai beaucoup. Après je mènerai des tests et je partagerai mon travail si le résultat est concluant (j'aurai une bonne raison de découvrir cocoapods)
Mots clés:
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
On peut faire de l'introspection avec le Runtime. En particulier lister les variables d'instance, les propriétés et les méthodes, et savoir de quelle classe une classe hérite.
Cependant, j'aimerais plutôt savoir quels sont les manques que tu as pu observer pour en discuter; il y a peut-être déjà une solution intégrée.
Je me suis heurté a un soucis relativement con qui m'a demandé d'adapter un peu.
Quand on utilise beaucoup le KVO et les bindings comme moi y'a certains trucs qu'on trouve un peu bizarre et rigides.
Par exemple j'ai une classe qui gère un couleur et qui en fait un peu plus que NSColor donc qui ne peut pas être une subclass de cette dernière (je rentre pas dans les détails c'est un projet en cours). Je dois pouvoir modifier les paramètres HSB et RGB. Les uns affectant les autres mais surtout la couleur. Si on fait un set sur la couleur c'est RGB et HSB qui sont changés mais qui eux même affectent la couleur... Si j'utilise keyPathsForValuesAffecting<key> alors je vais me retrouver avec une boucle infinie mais les observers seront notifiés.
La solution est de tout gérer manuellement. J'ai 2/3 méthodes dans une subclass de NSObject pour faire ça.
Le gros problème que j'ai c'est le undo management. C'est bien beau CoreData mais CoreData me rebute clairement. Pour gagner un undoManager je vais me taper 2 semaines à m'auto-former pour essayer de comprendre comment mettre en place ce que je pourrai faire facilement de manière traditionnelle. Alors j'essaie d'automatiser ça en surchargeant - (void)setValue:(id)value forKeyPath:(NSString *)keyPath pour qu'il enregistre les changements dans le undoManager (idée piquée à yoann dans un vieux topic) mais il me faudrait des moyens de contrôler tout ça plus finement. Comme par exemple un + (NSDisctionnary)undoManagerOptionFor<key> et je pense que c'est faisable.
(Je sais pas si ma prose est très claire et m'en excuse je suis sous médication un peu forte pour mon dos )
Voilà j'ai un peu creusé l'idée :
J'ai une méthode de classe :
Elle me permet de préciser quelles keys vont ajouter une entrée dans le undoManager.
J'ai également :
Pour le moment les vrais keyPaths ne passeraient pas vu que je ne gère pas la syntaxe avec les points (ça viendra après ça). Pour ce qui est du selector sur le setter je ne pense pas qu'il y ait un soucis vu que c'est toujours set<Prop_name>: ^^
Maintenant le problème qui reste c'est qu'il n'y a que le UNDO qui fonctionne le REDO ne veut rien savoir
Par contre, ça a quand même une grosse limitation: il faut absolument appeler -setValue:forKeyPath: pour modifier la propriété. De fait, l'undo fonctionne effectivement quand on la modifie par un binding, mais pas quand on passe par l'accesseur.
Pour moi, certes, ça fait gagner du temps en codage, mais c'est une demi-solution.
Oui effectivement ça fonctionne mais ça limite pas mal... (j'ai corrigé le code d'au-dessus qui avait un sale bug, au passage)
Quelle serait la bonne pratique alors ? Implémentation directe dans les setters ? Dans le contrôleur ?
Je trouve assez peu d'exemple correct évitant le boilerplate sur le net
Mon expérience est qu'il faut coder l'undo au niveau des setters. Ce qui implique qu'il faut passer l'undo manager à tous les objets... je n'ai pas de meilleure solution à te proposer.
A contrario de Céroce, j'ai pour habitude de considérer NSUndoManager comme un objet exclusivement lié à mes contrôleurs. Les objets models et views n'en voient donc pas la couleur mais sont capables de s'auto décrire et modifier à loisir sur demande du contrôleur qui les manipulent.
Mais je dois dire que le :
de Mala m'intéresse au plus au point
Tu pourrais m'en dire plus ? Si tu ne veux pas me donner de code je comprendrai aisément
Je pense que je ne te serais malheureusement guère utile car je code quasi exclusivement à l'ancienne. Je conserve donc une parfaite maà®trise de mes objets (view ou model) dont toute modification passe par le(s) contrôleur(s).
Néanmoins, dans le cas particulier de KVO qui t'intéresse, as-tu pensé aux notifications? Au lieu d'enregistrer lui même les données, l'objet enverrait juste une notification (NSNotification) avant sa modification. Le contrôleur, qui chapeaute tes objets, est à l'écoute et il peut alors faire son travail en interrogeant l'objet qui l'a notifié pour sauvegarder son état. C'est un peu plus lourd mais cela me semblerait plus respectueux du paradigme MVC. A méditer...
Le undo reste une superbe fonctionnalité de CoreData.