[Résolu] Outlineview et sauvegarde des items dépliés ou pliés...
LeChatNoir
Membre, Modérateur
Salut,
J'ai une outlineView qui fonctionne (ouehhhh !).
Les objets qu'elle affiche sont conforme au NSCoding protocol et à l'affichage de l'outlineview, ca désarchive bien et à sa fermeture, ca archive bien.
Par contre, j'ai découvert la possibilité de sauvegarder la configuration de l'outline (avec autosaveName) et également de la configuration des items dépliés ou pas (ceux qui ont des fils).
Ca se fait avec setAutosaveExpandedItem.
Quand on souhaite utiliser cette mécanique par contre, il faut ajouter ces 2 méthodes dans le delegate :
- (id)outlineView:(NSOutlineView *)outlineView persistentObjectForItem:(id)item
et
- (id)outlineView:(NSOutlineView *)outlineView
Je les ai défini telles que :
- (id)outlineView:(NSOutlineView *)outlineView persistentObjectForItem:(id)item
{
  return [NSKeyedArchiver archivedDataWithRootObject:item];
}
- (id)outlineView:(NSOutlineView *)outlineView itemForPersistentObject:(id)object
{
  return [NSKeyedUnarchiver unarchiveObjectWithData:object];
}
Bon ben ca se plante sur un message "selector not recognize" étrange dans mon encodeWithCoder mais là n'est pas (encore) la question.
Je me demandais simplement si ces fonctions ne faisaient pas plus que sauver la configuration des items dépliés/pliés...
Par ce qu'en tentant de debugger, je m'aperçois qu'il alloue/désalloue carrément mes objets perso...
Faut il alors laisser tomber le désarchivage à l'ouverture et l'archivage à la fermeture ou pas ?
Mais peut être faut il que je résolve d'abord mon erreur de encode...
Si quelqu'un a déjà expérimenté ça, je suis preneur de ses retours...
J'ai une outlineView qui fonctionne (ouehhhh !).
Les objets qu'elle affiche sont conforme au NSCoding protocol et à l'affichage de l'outlineview, ca désarchive bien et à sa fermeture, ca archive bien.
Par contre, j'ai découvert la possibilité de sauvegarder la configuration de l'outline (avec autosaveName) et également de la configuration des items dépliés ou pas (ceux qui ont des fils).
Ca se fait avec setAutosaveExpandedItem.
Quand on souhaite utiliser cette mécanique par contre, il faut ajouter ces 2 méthodes dans le delegate :
- (id)outlineView:(NSOutlineView *)outlineView persistentObjectForItem:(id)item
et
- (id)outlineView:(NSOutlineView *)outlineView
Je les ai défini telles que :
- (id)outlineView:(NSOutlineView *)outlineView persistentObjectForItem:(id)item
{
  return [NSKeyedArchiver archivedDataWithRootObject:item];
}
- (id)outlineView:(NSOutlineView *)outlineView itemForPersistentObject:(id)object
{
  return [NSKeyedUnarchiver unarchiveObjectWithData:object];
}
Bon ben ca se plante sur un message "selector not recognize" étrange dans mon encodeWithCoder mais là n'est pas (encore) la question.
Je me demandais simplement si ces fonctions ne faisaient pas plus que sauver la configuration des items dépliés/pliés...
Par ce qu'en tentant de debugger, je m'aperçois qu'il alloue/désalloue carrément mes objets perso...
Faut il alors laisser tomber le désarchivage à l'ouverture et l'archivage à la fermeture ou pas ?
Mais peut être faut il que je résolve d'abord mon erreur de encode...
Si quelqu'un a déjà expérimenté ça, je suis preneur de ses retours...
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
J'ai trouvé comment fonctionne la sauvegarde/restauration de l'état de l'outlineview.
First :
dire qu'on veut que ca soit sauver via :
[outlineView setAutosaveName:@UnNomSousLequelSeraSauvéeaLConfDeLaOutline];
[outlineView setAutosaveExpandedItems:YES];
J'ai l'impression qu'il utilise le NSUserDefault en arrière plan l'air de rien...
Second :
Implémenter les 2 méthodes de persistance à savoir "- (id)outlineView:(NSOutlineView *)outlineView itemForPersistentObject:(id)object" et "- (id)outlineView:(NSOutlineView *)outlineView persistentObjectForItem:(id)item".
Voyons la première : - (id)outlineView:(NSOutlineView *)outlineView itemForPersistentObject:(id)object
elle est appelée quand l'outline s'affiche et qu'elle essaye de récupérer l'état de chaque item (collapse ou pas).
Il faut donc, à partir de ce qu'on a sauvé (=> cf. explication de la seconde méthode), renvoyer l'item correspondant.
Voyons la seconde : - (id)outlineView:(NSOutlineView *)outlineView persistentObjectForItem:(id)item
Celle ci est appelée chaque fois qu'on déplie ou plie un item (et ce pour sauvegarder son état). C'est là qu'il faut envoyer l'item à sauvegarder.
Bon jusque là , vous allez me dire "C'est exactement, ce qui est marqué dans la doc".
Oui mais voilà , ce que j'avais pas capté, c'est qu'il met ça dans une property list ou un truc du style et que si les items de l'outlineview sont des objets customisés (comme c'est le cas pour moi) dans lesquels il y q des types non "property listables", ben ca marche pas et ca dit pas grand chose...
Donc dans ce cas, il faut :
* renvoyer l'item identifié par un identificateur unique qu'on récup' via le paramètre "object" de la méthode (ce qui oblige à parcourir l'arbre dans mon cas pour rechercher l'objet) ; ca dans la première méthode,
* renvoyer un identificateur de "item" qui soit compatible "property list" dans la 2eme méthode.
Bon, j'espère que c'est clair et que ca servira un jour à quelqu'un :-)
a+
Et pis tiens, je m'applaudis pour une fois que je me débrouille tout seul :adios!:
Tu entends quoi par "objets customisés". Des objets que tu créais toi même ?
Par objet customisé, oui, en fait, il s'agit de sous-calsse de NSObject à moi dans laquelle je met ce que j'ai envie.
Ce que je voulqis dire par là , c'est que ce ne sont pas de simples NSString ou des trucs comme çq.
Dedans, j'ai des types style NSImage qui ne peuvent être mis dans une property list d'où le problème que j'ai rencontré !
a+
J'ai bien une idée mais elle me semble pas "propre" (récupérer les informations directement dans les préférences).
Donc, si je comprends bien, avec les objects NSString, cocoa se débrouille tous seul mais avec des objects perso, c'est à moi de faire le bouleau.
Non non. Je me suis mal exprimé en fait.
C'est bien Cocoa qui fait tout.
Le seul truc c'est qu'en fait, dans les 2 méthodes de persistences à définir si tu veux sauver l'état plié/déplié de ton outline, il faut pouvoir encoder/décoder les objets de l'outline pour qu'il les archives/désarchive d'un fichier de sauvegarde (qui semble être les prefs mais c'est même pas sûr, j'ai pas vérifié).
Le problème, c'est que ton objet ne doit alors contenir que des types acceptés par les property list.
Si ca n'est pas le cas, il suffit de se débrouiller pour archiver un identifiant de ton objet seulement (un style de clé unique). Ca reste hyper simple du coup et on peut considérer que c'est Cocoa qui fait tout.
Je suis peut être pas super clair mais c'est tout simplement parce que je suis passé à autre chose depuis et je ne me rappelle déjà plus franchement de tous les tenants et aboutissants...
En gros, dans ovl:... persistentObjectForItem, je renvoie l'identificateur de mon objet, et dans l'autre, je cherche l'objet ayant pour identificateur "object" (qui est le paramètre de la méthode) et le renvoit.
J'ai été obligé de faire comme ça (ça y est, les détails me reviennent, j'suis pas si vieux que ca finalement !!!) car mes objets forment une hiérarchie. C'est un arbre en fait (dans un objet, j'ai un pointeur vers un objet père et un tableau de pointeurs vers des objets fils).
Or les Archiver et UnArchiver archivent ton objet et tous ceux liés à ton objet => donc quand tu fais un encodeWithCoder de ton objet, il archive tout ton arbre !!!!!
Bref, pour cette raison et pour d'autres (ce fameux identifieur va me servir pour plein d'autres trucs !) j'ai opté pour la solution sus citée.