[Résolu] "Magie" Core Data: encore une explication souhaitée

berfisberfis Membre
avril 2015 modifié dans API AppKit #1

Bonjour,


 


Il n'y a rien de magique dans Core Data, nous sommes d'accord, mais là  j'ai un truc qui fonctionne alors qu'il ne devrait pas (en principe) et j'aimerais savoir pourquoi.


 


Je sous-classe souvent des NSArrayControllers, et maintenant je fais pire: je sous-classe mes propres NSArrayControllers...


 


Comme deux NSArrayControllers (qui gèrent des Entities différentes) ont pas mal de comportements similaires, j'ai décidé de créer une classe abstraite BasicController dont héritent PlaceController (entité Place) et ThingController (entité Thing). Les entités Place et Thing dérivent elles-mêmes d'une entité abstraite Basic, qui leur fournit des propriétés communes, dont un set d'erreurs.


 


Ces deux contrôleurs sont instanciés par IB et ont les outlets sur le managedObjectContext du document. BasicController ne l'est pas (puisqu'il est abstrait).


 


A un moment donné, j'ajoute une erreur à  l'une des deux entités via son contrôleur, qui appelle la méthode de BasicController. Elle fait ceci:



- (IBAction)addError:(id)sender
{
Error *error = [NSEntityDescription insertNewObjectForEntityForName:@Error inManagedObjectContext:self.managedObjectContext];
Basic *basic = self.selectedObjects.lastObject;
[basic addErrorsObject:error];
[self rearrangeObjects];
}

... et ça marche.


 


Mais comment? Je sais que NSArrayController hérite de NSObjectController, qui possède la propriété managedObjectContext, mais par quel miracle (peut-être dangereux) BasicController connaà®t-il le bon contexte? C'est sûrement documenté quelque part, mais je précise que BasicController n'apparaà®t pas dans IB, qu'il n'a aucun outlet sur le document, que je ne l'initialise même pas...


 


Vous avez une explication?


Réponses

  • Heu bah c'est de l'héritage là  hein...


     


    Ton PlaceController a été réglé dans IB avec le bon managedObjectContext. Donc quand les méthodes hérités l'utilisent, bah elles y ont accès...


     


    Au passage, mauvaise pratique de sous classer NSArrayController. Trop opaque comme objet pour que ce soit updateproof.


  • Salut yoann,


     


    Mais là  c'est pas de l'héritage... les deux contrôleurs n'implémentent pas la méthode addError, c'est la méthode générique qui est appelée. Un peu comme si la classe parente héritait d'une propriété d'une classe fille. Je ne dois pas être à  mon affaire.



     


    Au passage, mauvaise pratique de sous classer NSArrayController. Trop opaque comme objet pour que ce soit updateproof.



    Attention, je ne bidouille pas dans NSArrayController, je rajoute des méthodes, comme on le ferait à  une NSView. Par exemple, l'arrayController est chargé de vérifier la cohérence de certaines propriétés de son contenu, il est pratique (via ses arrangedObjects) de le faire directement. Si les contrôleurs ne peuvent pas jouer leur rôle d'intermédiaire entre le modèle et la tableView, qui va le faire?


     


    Ce n'est pas la première fois que je vois cette remarque, cependant. Mais Hillegass lui-même le fait dans un de ses exemples assez basiques, et je ne vois pas le risque. Ce n'est pas comme si j'allais bidouiller dans un cluster comme NSDictionary...




  • Mais là  c'est pas de l'héritage... les deux contrôleurs n'implémentent pas la méthode addError, c'est la méthode générique qui est appelée. Un peu comme si la classe parente héritait d'une propriété d'une classe fille. Je ne dois pas être à  mon affaire.




     


    Pourtant dans ton premier post :


     




    j'ai décidé de créer une classe abstraite BasicController dont héritent PlaceController (entité Place) et ThingController (entité Thing).




     


     


    Donc tu es bien dans une relation d'héritage. Je ne comprends pas ton soucis.


     


     


     


     


     





    Attention, je ne bidouille pas dans NSArrayController, je rajoute des méthodes, comme on le ferait à  une NSView. Par exemple, l'arrayController est chargé de vérifier la cohérence de certaines propriétés de son contenu, il est pratique (via ses arrangedObjects) de le faire directement. Si les contrôleurs ne peuvent pas jouer leur rôle d'intermédiaire entre le modèle et la tableView, qui va le faire?


     


    Ce n'est pas la première fois que je vois cette remarque, cependant. Mais Hillegass lui-même le fait dans un de ses exemples assez basiques, et je ne vois pas le risque. Ce n'est pas comme si j'allais bidouiller dans un cluster comme NSDictionary...


     



     


    Quelle garantie tu as qu'à  l'avenir Apple ne rajoute pas une méthode au nom identique ? Aucune.


     


    NSArrayController n'est pas franchement prévu pour être étendu contrairement à  NSObject ou NSView.



  • Donc tu es bien dans une relation d'héritage. Je ne comprends pas ton soucis.




     


     


    Je n'avais pas les yeux en face des trous je pense. Le self.managedObjectContext est lui aussi hérité, et donc fixé par la classe fille.


     


     



    Quelle garantie tu as qu'à  l'avenir Apple ne rajoute pas une méthode au nom identique ?



     


    Alors ça c'est valable pour toutes les classes. C'est pourquoi il faudrait préfixer jusqu'aux méthodes... ou alors choisir le français mais j'ai toujours trouvé moche de mélanger les langages comme if (monPortemonnaie isEqualTo ensembleVide)...

  • AliGatorAliGator Membre, Modérateur
    Autant il y a certaines classes pour lesquelles Apple indique clairement dans la doc qu'il ne faut pas les sous-classer, qu'elles ne sont pas prévues pour et que ce n'est pas une bonne idée, autant j'ai jamais compris pourquoi y'en a tant qui disaient que NSArrayController ne devait pas être sous-classé... (à  ce moment là  il ne faut jamais sous-classer NSView ni NSSplitController ni NSWindow, ni NSManagedObject... on ne sait jamais !)

    yoann si tu retrouves la documentation officielle qui indique que pour NSArrayController c'est effectivement à  ne pas faire, je suis intéressé. Car sinon, comme Berfis, je ne vois pas trop en quoi NSArrayController ferait exception par rapport aux autres ?
  • yoannyoann Membre
    avril 2015 modifié #7


    Autant il y a certaines classes pour lesquelles Apple indique clairement dans la doc qu'il ne faut pas les sous-classer, qu'elles ne sont pas prévues pour et que ce n'est pas une bonne idée, autant j'ai jamais compris pourquoi y'en a tant qui disaient que NSArrayController ne devait pas être sous-classé... (à  ce moment là  il ne faut jamais sous-classer NSView ni NSSplitController ni NSWindow, ni NSManagedObject... on ne sait jamais !)


    yoann si tu retrouves la documentation officielle qui indique que pour NSArrayController c'est effectivement à  ne pas faire, je suis intéressé. Car sinon, comme Berfis, je ne vois pas trop en quoi NSArrayController ferait exception par rapport aux autres ?




     


    NSArrayController est ouvert à  la sous-classe, c'est spécifié dans la documentation d'Apple.


     


    Ce n'est pas pour autant que ce n'est pas une mauvaise idée.


     


    C'est une classe liée à  CoreData, qui propose un fonctionnement complexe, qui est assez peu documenté. Son unique rôle est de simplifier le fonctionnement de CoreData.


     


    N'importe quel développeur OS X avec un minimum d'expérience te dira que c'est une assez mauvaise idée de le sous-classer, l'encapsuler est bien plus sage vis à  vis des blagues habituelles d'Apple et plus propre en terme de conception.


     


    Par exemple, j'ai déjà  eu des NSArrayController sur OS X qui ne se comportaient pas de la même manière selon s'ils étaient encapsulé dans un NSObject ou un NSViewController.


     


    NSArrayController est un objet beaucoup trop opaque pour être sous classé avec confiance.


     


     


    Pour ma part vis à  vis de la doc d'Apple je considère trois scénario pour pas avoir d'emmerde :


    • je sous-classe si c'est clairement marqué en entête que c'est ouvert à  la sous-classe ;
    • si ce n'est pas en entête mais que c'est précisé pour certaines méthodes, je sous-classe uniquement pour surcharger ces méthodes là  ;
    • dans tous les autres cas, que ce soit explicite ou non, je ne sous-classe pas.
  • CéroceCéroce Membre, Modérateur
    avril 2015 modifié #8


    yoann si tu retrouves la documentation officielle qui indique que pour NSArrayController c'est effectivement à  ne pas faire, je suis intéressé. Car sinon, comme Berfis, je ne vois pas trop en quoi NSArrayController ferait exception par rapport aux autres ?




    Je partage totalement l'avis de yoann.


    Je le déconseille systématiquement pour les mêmes raisons (classe qui fait trop de chose, mal documentée). C'est toujours une mauvaise idée de sous-classer une classe dont on comprend mal le fonctionnement. Je m'y suis cassé les dents, parce que j'ai surchargé une méthode qui était appelée par une autre en interne, et ça faisait n'importe quoi.


     


    Je préfère instancier une sous-classe de NSObject dans mon xib, dans lequel je crée les actions. Je peux créer une outlet sur le NSArrayController, si besoin. Je n'y vois aucune limitation.


Connectez-vous ou Inscrivez-vous pour répondre.