[Résolu] - NSArrayController, Sort Descriptors et bindings

skimpyskimpy Membre
mai 2013 modifié dans API AppKit #1

Bonjour,


 


J'ai un problème de tri dans une NSTableView. Celle-ci est lié à  un NSArrayController qui est paramètré entre autre avec l'option Auto Rearrange Content (le contenu est bindé sur un Managed Object Context). J'ai bindé le Sort Descriptors du NSArrayController à  une méthode sortDescriptors comme indiqué dans la doc Apple. J'ai donc dans mon File's Owner, la méthode suivante :


 


- (NSArray *)sortDescriptors
{
return [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@name ascending:YES]];
}

et dans mon awakeFromNib, ceci pour la NSTableView :



[ibGroupsTableView setSortDescriptors:[self sortDescriptors]];

Lorsque j'ajoute des données, celles-ci ne sont pas triées. Par contre, si je quitte l'application et que je la relance, c'est bon.


 


Auriez-vous une idée ?


 


Merci.


Réponses

  • berfisberfis Membre

    Bonjour,


     


    Il faut passer la message -rearrangeObjects au contrôleur en fin d'édition des données.


  • skimpyskimpy Membre
    mai 2013 modifié #3


    Bonjour,


     


    Il faut passer la message -rearrangeObjects au contrôleur en fin d'édition des données.




    Bonjour berfis,


     


    Je vais tester mais c'est assez déroutant car dans le lien suivant (https://developer.apple.com/library/mac/#technotes/tn2203/_index.html#//apple_ref/doc/uid/DTS40011838) il est stipulé qu'à  partir de 10.5, il n'est plus nécessaire d'appeler cette méthode :


     



     Improvements to Mac OS X 10.5


    Thanks to the addition of the "Auto Rearrange Objects" feature of NSArrayController for 10.5, you no longer have to call:


    [myArrayController rearrangeObjects];


    To use the "Auto Rearrange Objects" feature either:


     


    1. Set the "Auto Rearrange Objects" checkbox for your NSArrayController in Interface Builder.
    2. Call [myArrayController setAutomaticallyRearrangesObjects:YES]; in your code.

     


    Names added to the array controller will automatically be sorted with the rest of the list.



     


    Est-ce que ça pourrait venir du fait que j'utilise un MOC temporaire pour faire l'insertion des objets ? Le MOC principal étant enregistré auprès du centre de notification pour recevoir la notification NSManagedObjectContextDidSaveNotification.


     


    Merci.


  • berfisberfis Membre
    mai 2013 modifié #4

    Oui... je sais... de sorte qu'entre les sort descriptors ajoutés par code, ceux définis dans IB, les cases "Auto" cochées, on finit par s'y perdre et manifestement cocoa aussi.


     


    Décoche l'auto, enlève le sort descriptor de IB, et ajoute setSortDescriptor et rearrangeObjects par code. C'est peut-être dommage mais ça a le bon goût de fonctionner.


     


    De plus, si la TableView est liée au contrôleur, c'est lui qui va faire le travail. Inutile d'ajouter un sort descriptor à  la TableView.


  • Es tu certain que ton NSArrayController est au courant des nouveaux objets ?


    A priori oui puisque tu utilises Core Data mais même avec Core Data il me semble qu'il faut toujours passer par des méthodes keyValueCodingProtocol comme insertObject:(id) inMyObjectsAtIndex:(NSUInteger)index;.


    En général quand les bindings ne "marchent pas" c'est souvent qu'ils n'ont pas été "déclenchés".


    rearrangeObjects lui fait prendre en compte les nouveaux objets.


  • berfisberfis Membre

    Comme le dit laudema, les bindings n'ont pas été "déclenchés", cela signifie que l'ajout de nouveaux enregistrements à  la table ne sont pas KVO. Le KVO/KVC est une magie... un peu noire qui nécessite à  elle seule un chapitre de documentation:


    https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueCoding/Articles/KeyValueCoding.html


     


    Un ArrayController "branché" sur un ManagedObjectContext est probablement modifié pour prendre en compte le KVO avec Core Data (ainsi que mettre à  jour le "Undo/Redo"). Mais tous les bindings "maison" lui passent un peu au-dessus de la tête et c'est en cela que -rearrangeObjects corrige le tir.


  • skimpyskimpy Membre
    mai 2013 modifié #7

    J'ai supprimé tout ce qui était bindé via IB et je l'ai mis dans mon awakeFromNib



    [groups setAutomaticallyRearrangesObjects:YES];
    [groups setSortDescriptors:self.sortByName];

    Ca n'a pas résolu le problème. J'ai aussi rajouté ça pour voir si le KVO fonctionnait :



    [groups addObserver:self
    forKeyPath:@arrangedObjects
    options:NSKeyValueObservingOptionNew
    context:nil];

    Je pense que c'est OK car quand je fais un save sur mon MOC "secondaire", il envoie la notification NSManagedObjectContextDidSaveNotification qui est reçu par mon MOC principal et juste après je reçois la notification arrangedObjects. Dans la méthode observeValueForKeyPath..., j'ai choisi d'afficher le keyPath et l'objet et voilà  la log qui s'affiche :



    [MYGroupController observeValueForKeyPath:ofObject:change:context:](0x106e00610) keyPath: arrangedObjects
    Object:
    <NSArrayController: 0x106e018d0>[entity: MYPerson, number of selected objects: 1]

  • skimpyskimpy Membre

    Pour info, le problème vient de l'option "Uses Lazy Fetching" du NSArrayController ... Sans cette option activée, le tri fonctionne parfaitement.


     


    L'autre problème maintenant, c'est que j'ai besoin du Lazy Fetching ...


  • berfisberfis Membre

    Je ne sais pas si le contrôleur peut effectuer un tri sur des faults... ça me paraà®t du même genre que trier des chaussettes que tu n'as pas encore achetées...


  • laudemalaudema Membre
    mai 2013 modifié #10


    Pour info, le problème vient de l'option "Uses Lazy Fetching" du NSArrayController ... Sans cette option activée, le tri fonctionne parfaitement.


     


    L'autre problème maintenant, c'est que j'ai besoin du Lazy Fetching ...




     


    Finalement c'était bien un problème de liaison non rafraichie par défaut de "trigger action".


    A première vue c'est un problème connu : si on cherche NSArrayController uses lazy fetching NSSortDescriptor sur Google on lit des choses comme


     



    NSArrayController with lazy fetching enabled and NSSortDescriptors are not the best friends



     


    La solution pour waschhauss media indiquée ici est de faire



    [myArrayController fetch:self]

    à  la fin de l'opération.


  • skimpyskimpy Membre
    mai 2013 modifié #11

    Merci laudema et berfis pour votre aide. C'est tout bon maintenant !


     


    Edit : finalement, au démarrage de l'appli quand le Uses Lazy Fetching est activé avec le sortDescriptors, il charge tout ... J'ai fait le test :


    - ULF activé et sortDescriptors désactivé : 34 MB utilisation mémoire


    - ULF activé et sortDescriptors activé : 92 MB


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