Encodage classe mère multiple
Mulot
Membre
Me revoilà , pour de nouvelles aventures chocolatées !
Voilà j'ai mon application qui est basée sur le modèle NSDocument.
Mon contrôleur (myDocument) possède une table où je stocke les "AccountOwner" qui sont crées dans mon applis. Chaque AccountOwner possède un tableau de compte, et chaque compte possède un tableau d'opérations.
Je ne pense pas que de ce côté là il y ai un problème, j'ai ajouté le protocole et surchargé les méthodes du protocole NSCoding.
Mon contrôleur contient donc une table mutable contenant des AccountOwners, possède deux pointeurs de type Account et AccountOwner vers des objets qui sont contenus dans la table précédente. Ils pointent sur l'utilisateur et le compte courant dans l'appli, je n'ai donc pas fait d'alloc pour ces simples pointeurs.
De plus, j'ai aussi une floppée de booléens dans mon controller, en plus des outlets (mais ceux si n'ont rien a voir avec l'archivage).
Je pensais donc bien faire en rendant ma classe myDocument compatible avec le protocole NSCoding.
J'ai donc ajouté une méthode encodeWithCoder: (NSCoder*) aCoder;
Ensuite dans ma méthode dataRepresentationOfType:
j'ai mis:
Ma méthode de décodage pour myDocument est comme ceci:
J'ai mis des petis NSLog dans mes méthode encode, et je remarque que lorsque je sauvegarde mon document, il encode ce qu'il faut correctement, mais le fait plusieurs fois d'affilée ! Je ne vois pourtant pas de "boucle".
Un autre point, est-ce que mes booleens et mes pointeurs sotn "encodés" et "décodés" comme il faut ? C'est à dire que l'objet pointé par currentUser est déjà archivé, on notera juste sa référence dans la table de stockage, non ? Et ma méthode de décodage refera bien pointer currentUser sur celui encodé auparavant ?
Un autre point, pour la méthode loadRepresentationOfType, j'ai quelques doutes avec ma démarche d'encoder le fichier de type NSDocument.
Bon là j'ai de gros doutes, lorsque j'ai testé d'ouvrir un fichier enregistré rien ne se passe. Mais je ne sais pas si ce que j'ai fait est bon, puisque d'un coté j'encode tout mon myDocument, et là je ne touche qu'à la table. SI vous pouviez m'éclairer quelque peu !
Voilà j'ai mon application qui est basée sur le modèle NSDocument.
Mon contrôleur (myDocument) possède une table où je stocke les "AccountOwner" qui sont crées dans mon applis. Chaque AccountOwner possède un tableau de compte, et chaque compte possède un tableau d'opérations.
Je ne pense pas que de ce côté là il y ai un problème, j'ai ajouté le protocole et surchargé les méthodes du protocole NSCoding.
Mon contrôleur contient donc une table mutable contenant des AccountOwners, possède deux pointeurs de type Account et AccountOwner vers des objets qui sont contenus dans la table précédente. Ils pointent sur l'utilisateur et le compte courant dans l'appli, je n'ai donc pas fait d'alloc pour ces simples pointeurs.
De plus, j'ai aussi une floppée de booléens dans mon controller, en plus des outlets (mais ceux si n'ont rien a voir avec l'archivage).
Je pensais donc bien faire en rendant ma classe myDocument compatible avec le protocole NSCoding.
J'ai donc ajouté une méthode encodeWithCoder: (NSCoder*) aCoder;
<br /><br />- (void) encodeWithCoder: (NSCoder*) aCoder {<br /><br />//encoding the dictionnary<br />[aCoder encodeObject: userDictionary];<br /><br />//encoding pointers<br />[aCoder encodeObject: currentUser];<br />[aCoder encodeObject: currentAccount];<br /><br />//encoding booleans<br />[aCoder encodeValueOfObjCType:@encode(BOOL) at &operationDesignationSort];<br />...<br />...<br /><br />}<br />
Ensuite dans ma méthode dataRepresentationOfType:
j'ai mis:
<br />...<br />//ici self est myDocument<br />return [NSArchiver archivedDataWithRootObject: self];<br /><br />
Ma méthode de décodage pour myDocument est comme ceci:
<br />...<br /><br />if (self = [super init] ){<br />//setUserDictionary est un setteur "normal" retain, release puis pointe sur le param<br />[self setUserDictionary: [aCoder decodeObject]];<br /><br />currentUser = [aCoder decodeObject];<br />currentAccount = [aCoder decodeObject];<br /><br />[aCoder decodeValueOfObjCType: @encode(BOOL) at &operationDesignationSort];<br />...<br />}<br /><br />return self;<br />]<br /><br />
J'ai mis des petis NSLog dans mes méthode encode, et je remarque que lorsque je sauvegarde mon document, il encode ce qu'il faut correctement, mais le fait plusieurs fois d'affilée ! Je ne vois pourtant pas de "boucle".
Un autre point, est-ce que mes booleens et mes pointeurs sotn "encodés" et "décodés" comme il faut ? C'est à dire que l'objet pointé par currentUser est déjà archivé, on notera juste sa référence dans la table de stockage, non ? Et ma méthode de décodage refera bien pointer currentUser sur celui encodé auparavant ?
Un autre point, pour la méthode loadRepresentationOfType, j'ai quelques doutes avec ma démarche d'encoder le fichier de type NSDocument.
<br />- (BOOL) loadRepresentationOfType: (NSData*)dat ofType:(NSString*) type {<br /><br />//release userDictionary<br />[userDictionary release];<br /><br />userDictionary = [[NSUnarchiver unarchiveObjectWithData:data]retain];<br />[self updateUI];<br />return YES;<br /><br />}<br />
Bon là j'ai de gros doutes, lorsque j'ai testé d'ouvrir un fichier enregistré rien ne se passe. Mais je ne sais pas si ce que j'ai fait est bon, puisque d'un coté j'encode tout mon myDocument, et là je ne touche qu'à la table. SI vous pouviez m'éclairer quelque peu !
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
file:///Developer/ADC%20Reference%20Library/documentation/Cocoa/Conceptual/Archiving/index.html
Lorsque tu charges un doc, loadData.. est appelé avant awakeFromNib donc les actions que tu feras sur des outlets dans le setupUI devront être refaites dans le awakeFromNib ...
Classe MyDocument
- (NSData *)dataRepresentationOfType:(NSString *)aType
{
NSData *data;
data = [NSKeyedArchiver archivedDataWithRootObject:contentArray];
return data;
}
- (BOOL)loadDataRepresentation:(NSData *)data ofType:(NSString *)aType
{
contentArray = [[NSKeyedUnarchiver unarchiveObjectWithData:data] retain];
return YES;
}
Classe Node
#pragma mark ++ Coder Methods ++
-(void) encodeWithCoder:(NSCoder *)coder
{
[coder encodeObject:name forKey:@NodeName];
[coder encodeObject:children forKey:@NodeChildren];
[coder encodeObject:elements forKey:@NodeElements];
}
-(id) initWithCoder:(NSCoder *)Â coder
{
self=[super init];
if(self){
name=[[coder decodeObjectForKey:@NodeName] retain];
children=[[coder decodeObjectForKey:@NodeChildren] retain];
elements=[[coder decodeObjectForKey:@NodeElements] retain];
}
return self;
}
J'ai fait l'impasse sur le test allowsKeyCoding
Quand le codage n'est pas en KeyedArchiver, on doit respecter l'ordre du codage dans le décodage.
Je n'utilise pas de KeyedArchiver/unarchvier parce que je n'en vois pas l'intérêt dans mon cas, et je respecte bien l'ordre d'encodage lors du décodage.
Mon soucis serait plus sur le fait que je fais implémenter le protocol NSCoding à ma classe NSDocument qui est le contrôleur.
J'ai suivit le même exemple que dans "Cocoa par la Pratique", sauf que dans l'exemple d'archivage, il n'y a pas de controler à encoder, le contrôleur contient juste un tableau d'objets implémentant le protocole NSCoding.
Dans mon cas j'ai une table aussi à encoder dans le contrôleur, mais j'ai aussi d'autres objets et variables. Faut-il donc que je rende mon contrôleur compatible avec le protocole NSCoding ?
Si oui l'objet racine à encoder doit être lui même non ?
Pourquoi j'obtient un "triple" encodage alors que mon arbre d'archivage est simple ? (Contrôleur possède une table d'objet AccountOwner, chaque AccountOwner a un tableau de Compte, chaque Compte a un tableau d'opération).
Pourtant lors d'un "cycle" d'encodage, tout se fait parfaitement bien à premiere vue.
Par exemple, suite à l'appel de la méthode dataRepresentationOfType, je passe bien dans la méthode encodeWithCoder de mon contrôleur, il encode la table, mon utilisateur dans la table est bien encodé, ensuite le compte de celui ci est bien encodé, et enfin l'opération dans le compte de l'utilisateur ets encodée. Ensuite mes pointeurs sont encodés, mes booléens sont encodés, mais ce cycle est refait plusieurs fois ensuite, un problème avec mes pointeurs ? Dois-je les encoder avec l'option encodeConditionalObject ? (puisque ces objets sont fatalements présent dans la table).
Merci pour vos réponses, l'archivage me faisait un peu peur, et je ne pense pas arriver à tout comprendre pour l'instant sur ce point non plus.
Au début tu encodes donc un tableau . Quelle est la nature de chaque objet de ton tableau, et respectent-ils NScoding ?
Comme mon exemple, il semble plus logique d'encoder la table, chaque objet de cette table devant respecter le protocole NSCoding
Je ne peux donc pas me permettre de faire :
Les objets contenus dans ma table implémentent tous le protocole NSCoding, ils s'encodent bien, chaque objet encodé appelle bien l'objet "enfant" qu'il faut Mon controlle encode ma table, ma table encode mon User, mon USer encode son compte, son compte encode son opération.
Le seul soucis est que ce cycle est fait 2 fois. J'ai mis un NSLog au début de ma méthode encodeWithCoder de myDocument.m, et ce NSLog est bien appellée deux fois. Etrange, n'y a til pas un appel "automatique" liée au fait que ça soit un document ou que je tente d'archiver self ?
J'obtient le même résultat si je n'encode pas mes pointeurs, ou si je les encode en conditional.
Il serait logique que lors du [NSArchiver archivedDataWithRootObject:self] une première demande de codage soit faite (encodeRootObject:), comme l'indique la doc
Root Object
An object graph is not necessarily a simple tree structure. Two objects can contain references to each other, for example, creating a cycle. If a coder follows every link and blindly encodes each object it encounters, this circular reference will generate an infinite loop in the coder. Also, a single object can be referenced by several other objects. The coder must be able to recognize and handle multiple and circular references so that it does not encode more than one copy of each object, but still regenerate all the references when decoding.
To solve this problem, NSCoder introduces the concept of a root object. The root object is the starting point of an object graph. To encode an object graph, you invoke the NSCoder method encodeRootObject:, passing in the first object to encode. Every object encoded within the context of this invocation is tracked. If the coder is asked to encode an object more than once, the coder encodes a reference to the first encoding instead of encoding the object again.
NSCoder does not implement support for root objects; NSCoder's implementation of encodeRootObject: simply encodes the object by invoking encodeObject:. It is the responsibility of its concrete subclasses to keep track of multiple references to objects, thus preserving the structure of any object graphs.
Donc si j'ai compris, lorsque je fais:
Cela veut dire que encodeObject est envoyé à self ? Donc en théorie, vu que ma classe implémente NSCoding, encodeObject devrait bien marcher, et donc encodeObject devrait appeler ou utiliser ma méthode encodeWithCoder que j'ai surchargé non ?
Je ne vois pas pourquoi il réencode le tout une deuxième fois à vrai dire, c'est quand même pas quelque chose de normal tout de même ?
De plus mon diagramme de classe est un arbre.
myDocument
_______ ______ _____|_____________________
| | | |
| | | |
userDictionary currentUser currentAccount boolean ...(...)
| | |
AccountOwner <---/ |
| |
Account <
/
|
Operation
Desole pour cet immondice mais mon mac est à l'étage ! Donc je ne remarque pas de cycle ou de référence croisées dans mon code. Si quelqu'un peut m'expliquer un peu plus en détails le principe de fonctionnement de NSArchiver, et qui se passe réellement de l'encodage du rootObject.
Merci !
Ce qui fait que dans readFromData, on est amené à transférer les données.
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)aType error:(NSError**) addError
{
NSLog(@reading from data);
id object=[[NSKeyedUnarchiver unarchiveObjectWithData:data] retain];
[self setValue:[object valueForKey:@number] forKey:@number];
[self setValue:[object valueForKey:@string] forKey:@string];
NSLog(@number:%d string:%@",[number intValue],string);
return YES;
}
[Fichier joint supprimé par l'administrateur]
Donc en fait pour le désarchivage, je dois déclarer un objet de type myDocument, qui sera retournée par le NSUnarchiver, et je prend les valeurs de cet objet, que je réaffecte à self donc ?
Par contre j'ai toujours mon soucis de double encodage, j'aimerai bien régler ce soucis avant de commencer le désarchivage, et je ne vois pas d'où ça pourrait venir.
Quelqu'un à une piste à me donner ?
Objective-C recommande en général de séparer
- le modéle (les données)
- le controleur
- la vue
c'est ce qu'ils appellent le principe Model-View-Controller
Si il est encore temps dans ton appli de le faire, le controleur possèderait un champ MyModel * model qui serait l'unique objet archivé et désarchivé en rootObject. C'est donc cettte classe qui serait compatible avec le protocole NSCoding, et non le controleur.
Autrement
je n'ai pas d'autres solutions que celles de recopier les données.
double encodage
à l'essai du code que je t'ai envoyé, on n'a pas cela, mais peut-être l'explication y est quand même :
Lors du désarchivage, la méthode init de la sous-classe est appelée : il faut bien que self existe avant l'appel de la méthode readFromData
Pour faire un controller avec un seul objet de type myModel, il faudrait que je "déplace" tout mes attributs dans cette classe myModel, avec les méthodes privées, les méthodes d'IB, ainsi que les outlets et l'implémentation des délégates et autres dataSource donc ?
Dans myDocument, il aura donc une méthode init du genre
Il faut donc je laisse les méthodes loadDataRepresentionOfType, readDataRepresentionOfType, et toutes celles propres à myDocument en fait dans myDocument.
D'un point de vue .NIB, il va falloir que j'instancie une classe de type MCModel dans le .NIB, et qu'elle soit l'unique outlet du FileOwner (myDocument) ?
Merci pour ta patience Philippe, je vais tacher de faire cette modification cette après midi, je vous tiendrez au courant.
à priori les delegate et data-source, les IBAction sont des méthodes de contrôle, elles doivent rester dans le controleur:
-Le modèle reçoit les données manipulées (=le fondamental pour reconstituer ton document) , et les méthodes comme encodeWithCoder: , initWithCoder:.
-Le contrôleur s'occupe des méthodes de gestion sur la vue, répercute les transformations du modèle décidées par l'utilisateur, et déclare les utilitaires nécessaires.
attention aux initiations multiples lors du désarchivage.
Les notifications se traitent à priori dans le contrôleur.
oui, et également les IBAction, les méthodes de mise à jour de l'interface graphique
non, le modèle n'a pas besoin d'être un outlet
Je pense que tu as voulu dire la méthode init de la super-classe plutôt non ?
Par contre je viens d'y penser à l'instant, je me rappelle dans "Cocoa par la Pratique", que l'auteur précise que si on cherche à faire implémenter le protocole NSCoding à une classe, il y a deux possibilitées:
- soit la super-classe implémente le protocole NSCoding, et dans ce cas dans le initWithCoder il faut faire:
- soit la super classe ne l'implémente pas et dans cas il faut simplement faire [super init].
Par contre je ne vois pas trop le lien entre la méthode initWithCoder et mon soucis que j'ai à l'encodage, pour l'instant je n'ai pas essayé le désarchivage, je préfère que mon archivage marche correctement avant de m'y lancer, pour éviter d'avoir des problèmes avec un archivage foireux.
Non pas exactement, j'ai rectifié dans le post précédent.
je pense qu'il y a un mic-mac dans ton code.
voilà le log sur l'essai que je t'ai proposé :
[Session started at 2007-08-21 14:56:20 +0200.]
-- Là je précise les valeurs d'un document Untitled--
2007-08-21 14:56:20.816 essaiCoderMultiple[2420] initializing
2007-08-21 14:56:21.398 essaiCoderMultiple[2420] controller did load nib, number=0 string=(null)
2007-08-21 14:56:39.261 essaiCoderMultiple[2420] new string is : toto
2007-08-21 14:56:42.867 essaiCoderMultiple[2420] new number is : 123
-- Là j'enregistre mon document, et le ferme --
2007-08-21 14:56:48.793 essaiCoderMultiple[2420] encoding with coder
-- Là , je le rouvre, et on voit bien qu'une initialisation d'instance a lieu avant readFromData --
-- comment cela se pourrait-il autrement puisque readFromData: est une méthode d'instance --
2007-08-21 14:56:57.875 essaiCoderMultiple[2420] initializing
2007-08-21 14:56:57.876 essaiCoderMultiple[2420] reading from data
2007-08-21 14:56:57.876 essaiCoderMultiple[2420] init with coder
2007-08-21 14:56:57.876 essaiCoderMultiple[2420] number in initWithCoder : 123
2007-08-21 14:56:57.876 essaiCoderMultiple[2420] toto
2007-08-21 14:56:57.876 essaiCoderMultiple[2420] number:123 string:toto
2007-08-21 14:56:57.878 essaiCoderMultiple[2420] controller did load nib, number=123 string=toto
Je ne peux qu'appuyer Philippe49, qui te conseille de repartir sur des bases saines. Fais une classe modèle propre, répondant au protocole NSCoding, dans laquelle tu implémentes tout tes setters/getters et méthode d'archivage, ensuite tu y verras beaucoup plus clair, et tu y gagneras du temps pour la suite du projet.
Bon je tente de reprendre ce que je voulais dire.
Le soucis c'est que mon appli est quasiment finie dans sa première version, et qu'il ne manque plus que l'archivage et quelque retouches pour être opérationnelle (bien que je vais ajouter pas mal de choses ensuite).
Si il faut simplement virer certaines méthodes de mon contrôleur, ajouter un attribut myModel à mon contrôleur et y mettre les ex méthodes privées de mon ex contrôleur, instancier ma classe myModel dans myDocument.NIB, remettre les outlets et IBactions à jour si les outlets vont dans l'objet myModel, et remplacer des self par myModel dans mon contrôleur, ça devrait aller, seulement j'ai peur de ne pas avoir bien codé et de voir réaparaitre des soucis.
Autrement, si je me met à faire cette "migration", il faut que mon contrôleur contienne :
- les delegates,
- les data sources,
- l'ajout d'objets (qui seront contenus dans l'attribut myModel) au centre de notification,
- méthodes d'actions,
- méthodes créés automatiquement pour un NSDocument,
- méthode init,
- les outlets ?
Pour ce qui est de ma méthode pour updater l'interface Philippe, ce n'est pas une méthode d'action, elle doit donc se trouver dans muModel non ? De plus je l'appelle par exemple lorsque la selection de ma tableView change, ou quand une combo box est modifiée, ou suite à un appel ou fin d'une feuille.
Pour les outlets, si ils sont dans mon contrôleur je devrais les mettre en scope protected puisque je me sert des outlets dans des méthodes qui seront présentes dans myModel.
Donc dans myModel, j'aurais :
- méthodes privées qui seront appelées soit par d'autre méthodes privées de myObject, ou par des méthodes d'action dans le contrôleur,
- méthode d'archivage de l'objet myModel qui devra être capable d'implémenter le protocole NSCoding.
Est-ce que ceci pourrait être quelque chose de bon à faire ? Je ne sais pas trop vu l'état actuel de l'appli et la façon dont j'ai (mal) codé ce projet, si ça sera faisable sans une boite d'aspirine.
D'ailleurs pour les personnes qui le souhaitent (et qui ont le temps et l'envie), je met mon projet actuel disponible, pour que vous puissez voir l'étendue des dégâts ! Faites pas attention à mes commentaires souvent stupides ou très mal formulés en anglais approximatif !
Attention, je risque de vous choquer dans mon utilisation de Cocoa ou dans le "style", j'ai utilisé des méthodes qui ne sont peut être pas les bonnes, alors qu'une autre aurait pu suffir (je pense notament à la gestion des comboBox en mode dataSource, pour ceux qui auront le courage de regarder).
Bien entendu je suis ouvert à toute critique constructive pouvant m'aider à mieux comprendre le model pattern MVC, et la philosophie Cocoa, et profiter de votre expérience.
[Fichier joint supprimé par l'administrateur]
c'est un peu ça, peut-être même seulement ça ...
Mais c'est vrai que vu l'état d'avancement de ton projet, cela risque d'avoir pas mal d'effets de bord ..
A toi de voir si ton projet est un essai à mener à bien, ou si tu veux en faire un produit que tu pourras ensuite mettre à jour ...Â
non, pas du tout
En fait myModel, c'est comme ce que tu as fait avec tes classes Account et AccountOwner : des stockeurs de données, relativement inertes.
Tu rajoutes un étage à ton système de données pour simplifier l'architecture de ton programme.
Ta liste de booléens est impressionnante, et peut être réduite à un seul int : connais-tu la méthode des drapeaux (flags) ?
 Â
La version actuelle sera aussi chiante à faire évoluer selon toi ?
J'ai pensé à rejouter pas mal de choses à ce projet, comme par exemple une exportation d'une opération vers iCal, pour une opération importante, via AppleScript (par exemple l'achat d'un nouvel iMac 24"!).
Aussi ajouter un "outil" statistique, comme par exemple différents diagrammes représentants les credits / Débits pour une durée donnée ou tels ou tels type d'opérations.
L'ajout de catégories pour chaque opération, ensuite statistiques pour chaque catégorie, ce genre de choses.
Donc dans mon cas précis avec le code actuel que j'ai, myModel contiendrait en fait un NSMutableDictionary contenant des AccountOwner, deux pointeurs de type Account et AccountOwner, ainsi que quelques autres variables (int et/ou booléens) ?
Si tu as regardé en vitesse mon code, est-ce que mes méthodes que j'appelle "méthodes privée" (enfin celles qui ne sont pas des IBAction), seront à leur place dans myModel? Comme par exemple celles du genre: createUser:, editAccount: , raiseCreateAccountSheet: et les autres ? Parce que ces méthodes sont en quelque sorte dépendantes de l'UI et des outlets qui sont dans la classe parente (le contrôleur).
J'ai peur de ne pas arriver séparer convenablement ce qu'il faut dans le contrôleur et myModel: par exemple pour créer un utilisateur, il faut que le nom et prénom ne soit déjà pas dans la table, sinon j'avertit l'utilisateur et je reset les champs de saisie, ou si je supprime un utilisateur, il faut que je remette à jour le string dans ma combobox adéquate, bref un tas de choses que je peux uniquement faire si je connais les éléments de l'UI et les outlets, je vois mal comment faire ça de façon générique (peut être avec des méthodes avec tout ce qui est nécessaire en paramètre ?).
Autres petite question, auriez vous un projet relativement simple ou un tutoriel où je puisse voir la mise en place d'un objet myModel dans un contrôleur ? Est-ce quasiment une obligation de passer par ce genre de modèle ?
Ouai, je me trimballe pas mal de booléens, rien que 6 pour le tri de mon tableau, vu que je n'utilise pas les bindings. De plus maintenant que je lance un tri quand on clique sur une entête de colonne, je peux plus resizer les colonnes !
Remplacer les booléens par un int, j'y ai pensé, mais il n'y pas longtemps à vrai dire, seulement lorsque j'ai ajouté un NSPopUpButton pour affichier uniquement les opérations de tel ou tel type (que je n'ai pas encore implémenté d'ailleurs, c'est juste joli pour l'instant).
Je ne connais pas la méthode des flags, mais il me semble avoir vu un article sur le forum là dessus, merci du tuyau !
Il faudrait plus qu'une lecture superficielle pour te répondre.
Non ce n'est pas une obligation de détacher physiquement (=créer une classe) le modèle du controleur.
C'est un peu comme l'utilisation des variables globales en C : au bout d'un certain de niveau de complexité, cela nuit, alors qu'au début on a l'impression que cela simplifie les choses. C'est un peu ce qui s'est passé avec ton problème d'archivage.
Je vais tenter de mettre ne application ma classe MCModel, en dupliquant mon projet (pas envie de ruiner l'ancien tout de même), si je galère de trop, je me pencherai sur mon ex-code, à savoir plus exactement le pourquoi du comment du double archivage.
En attendant je laisse le topic en suspend, j'aurais sûrements d'autres questions sur l'archivage et le désarchivage.
Les booléens ne sont-ils pas des choix de l'utilisateur à un moment donné? En ce cas, ils n'ont pas besoin d'être archivés dans le document enregistré, cela simplifie considérablement les fonctions d'encodage-décodage
Si ce sont des choix importants cela se fait traditionnellement dans les préférences.
Dans la méthode initWithCoder, le return self devrait être extérieur au if(}
Bon courage
Donc c'est vrai qu'il n'est pas nécessaire de les encoder, il suffira que je selectionne par default un item du NSPopUpButton lors du chargement du .NIB, merci de la remarque !
J'ai pourtant ma méthode d'archivage qui correspond à ceci dans mon controller:
Mon controlleur dispose d'une méthode encodeWithCoder: comme suit:
userDictionary est un simple NSMutableDictionary, contenant des AccountOwner (conforme au protocole NSCoding).
Cette méthode fonctionne convenablement puisque les méthodes encodeWithCoder: de AccountOwner, puis Account, puis Operation sont appellées dans l'ordre logique des choses (j'ai vérifié à coup de NSLog).
Le problème se situerait donc lors de encodeWithRootObject:, mais pourquoi ?
Je suis désolé de poster ça comme ça et de demander une éventuelle réponse, mais là je suis vraiment bloqué, et j'ai un besoin assez urgent de finir cette partie (Grisbi est un truc infame).
Pour la seconde option consistant à créer un modèle, je n'ai pas encore eu l'occasion de tester ce que j'ai commencé par manque de temps.
Merci de vos futures réponses.
Qu'il soit présent dans mon code ou non, le "double encodage" se fait toujours.
Est-ce qu'il y a un moyen de voir l'execution step by step dans XCode, peut être avec les breakpoint, bien que lors de crash d'applis, je n'arrive pas à debugger convenablement.
Par exemple quand j'ai un crash d'appli, je vois bien les méthodes appellées, mais dans la plus part des cas, je ne vois pas la ligne où l'erreur s'est produite, mais un bon vieux code assembleur, de suite ça refroidit. J'ai eu certains cas où je voyais une flèche rouge en face de l'endroit de l'erreur, mais là encore, comportement étrange, je n'ai pas réussi à aller dans ma méthode qui merdouillait.
En Java il suffit de suivre les stackTrace, et on remonte anisi du main, à la méthode contenant là ligne où l'erreur s'est prduite etc, pour finalement arrvier à LA ligne qui à causé le soucis. Y a-t-il un moyen similaire avec Xcode ?
Sinon pour en revenir au problème, comment est-ce que je peux voir chaque appel de méthode fait, pour comprendre si une méthode pourrait rappeler encodeWithRootObject ou une méthode similaire ?
a priori non,
As-tu essayé la compilation avec le mode Build > Build And Debug ?
(mettre un signet en face l'une des lignes de dataRepresentationOfType, et voit ton code s'exécuter pas à pas)
après tu utilises les boutons step-in et step-out qui font réaliser l'exécution pas à pas ou par bloc (de fonction engénéral)
J'ai tenté de faire ma classe myModel, mais j'ai encore quelques questions.
Le soucis c'est que ma classe myModel tel que je la voie sera dépendante de l'UI, et ça, ça me semble pas bon du tout, puisqu'il faut que j'aille rechercher des valeurs dans des NSTextField ou des NSComboBox.
De plus il faut que je passe mes outlets en scope public, pour que l'attribut myModel de mon controler puisse y avoir accès, ça aussi c'est ptet pas le top.
Enfin bref là je galère pour essayer de boucler ce petit projet bidon dans sa phase première.
J'ai pensé à utiliser du XML pour stocker les données, mais je pense que ça nécessitera plus de code, puisque imaginons que j'ai 2 comptes et 4 opérations dans chacun de mes comptes, il va falloir en fait que je recrée ces deux comptes et les opérations qu'ils contiennent, lors de la lecture de mon XML ?
Ca pourrait quand même être une solution efficace de stocker ces infos via un fichier XML ? Parce que là vu le bouzin pour essayer d'archiver un simple objet, ça me dégoutte déjà quelque peu de l'archivage, quand on le comapre avec la simplicité de l'archivage en Java.