Pb d'archivage/désarchivage

RadadaRadada Membre
01:03 modifié dans API AppKit #1
Salut à  tous : )

Je suis en train de faire un exo du bouquin du Aaron Hilleglass. Il faut faire une toute petite appli qui permet de dessiner des ovales (avec une NSBezierPath).
Pour les courageux (moi donc ^^), il faut ajouter la sauvegarde et l'annulation.
J'ai une classe GGPanel qui dérive de NSView et qui contient un NSBezierPath et un NSColor. J'ai ajouté les méthode encodeWithDecoder et initWithCoder pour sérialiser mes 2 objets.
Dans ma classe MyDocument, j'ai un pointeur sur le GGPanel et j'ajoute les méthodes qui vont bien( enfin, il doit forcement en manquer...) dans readFromData:ofType:error et dataOfType:error.
Mais si la sauvegarde à  l'air de fonctionner (le fichier de sauvergarde contient des données et ça ressemble à  ce que j'attends), le chargement des fichiers de sauvegarde ne fonctionne pas du tout. Pourtant je passe bien dans initWithCoder.
Ca doit surement être une bonne grosse erreur de débutant, mais je ne vois vraiment pas ce qui cloche.
Vala, merci : )))
«1

Réponses

  • RadadaRadada Membre
    01:03 modifié #2
    dans 1250432120:

    Salut à  tous : )

    Je suis en train de faire un exo du bouquin du Aaron Hilleglass. Il faut faire une toute petite appli qui permet de dessiner des ovales (avec une NSBezierPath).
    Pour les courageux (moi donc ^^), il faut ajouter la sauvegarde et l'annulation.
    J'ai une classe GGPanel qui dérive de NSView et qui contient un NSBezierPath et un NSColor. J'ai ajouté les méthode encodeWithDecoder et initWithCoder pour sérialiser mes 2 objets.
    Dans ma classe MyDocument, j'ai un pointeur sur le GGPanel et j'ajoute les méthodes qui vont bien( enfin, il doit forcement en manquer...) dans readFromData:ofType:error et dataOfType:error.
    Mais si la sauvegarde à  l'air de fonctionner (le fichier de sauvergarde contient des données et ça ressemble à  ce que j'attends), le chargement des fichiers de sauvegarde ne fonctionne pas du tout. Pourtant je passe bien dans initWithCoder.
    Ca doit surement être une bonne grosse erreur de débutant, mais je ne vois vraiment pas ce qui cloche.
    Vala, merci : )))


    Tant qu'à  y être, si vous avez des pistes (des pistes, pas la solution svp) pour l'annulation... Je sèche un peu : impossible d'utiliser l'undoManager (prepareWithInvokationTarget) puisqu'il n'y a pas moyen (enfin je crois) de soustraire une forme du path lorsqu'on utilise appendBezier..... Et je ne vois pas vraiment  comment utiliser addObserver... A moins d'utiliser un path à  chaque fois et de l'ajouter à  une liste, et on redessine la liste à  chaque fois. Mais ça me parait vachement lourd non???
    Meeeeeeeeeeeeeerci  ;) ;)
  • Philippe49Philippe49 Membre
    01:03 modifié #3
    dans 1250432120:

    J'ai ajouté les méthode encodeWithDecoder et initWithCoder pour sérialiser mes 2 objets.

    Peux-tu montrer ces deux méthodes , en précisant dans quel fichier elles sont implémentées ?

    dans 1250432120:

    Dans ma classe MyDocument, j'ai un pointeur sur le GGPanel et j'ajoute les méthodes qui vont bien( enfin, il doit forcement en manquer...) dans readFromData:ofType:error et dataOfType:error.

    Même demande.

    dans 1250432120:

    Mais si la sauvegarde à  l'air de fonctionner (le fichier de sauvergarde contient des données et ça ressemble à  ce que j'attends), le chargement des fichiers de sauvegarde ne fonctionne pas du tout.

    Plantage ? Non apparition de l'ovale ?


  • RadadaRadada Membre
    01:03 modifié #4
    dans 1250458772:

    dans 1250432120:

    J'ai ajouté les méthode encodeWithDecoder et initWithCoder pour sérialiser mes 2 objets.

    Peux-tu montrer ces deux méthodes , en précisant dans quel fichier elles sont implémentées ?

    dans 1250432120:

    Dans ma classe MyDocument, j'ai un pointeur sur le GGPanel et j'ajoute les méthodes qui vont bien( enfin, il doit forcement en manquer...) dans readFromData:ofType:error et dataOfType:error.

    Même demande.

    dans 1250432120:

    Mais si la sauvegarde à  l'air de fonctionner (le fichier de sauvergarde contient des données et ça ressemble à  ce que j'attends), le chargement des fichiers de sauvegarde ne fonctionne pas du tout.

    Plantage ? Non apparition de l'ovale ?

    Salut et merci pour ton post.
    J'ai mis le projet en pièce jointe du premier post, comme ça tu as tout. Dis moi si tu veux quand même que je les remette ici.
    Merci :)
  • Philippe49Philippe49 Membre
    01:03 modifié #5
    dans 1250491305:

    Dis moi si tu veux quand même que je les remette ici.

    Disons que j'aimerais que tu formules ta question de manière plus précise :
    • Qu'est-ce qui ne marche pas exactement, plantage ? non apparition de ce que tu attends ?
    • J'ai mis un NSLog() à  tel endroit dans le code (citer alors le code) et cela ne m'a pas donné ce que j'attendais,
    • J'en ai mis un autre ailleurs, et ...
    • ou j'ai lancé le debuggeur et il s'est passé tel chose ...

    En gros, la part d'analyse que tu as faite.
  • RadadaRadada Membre
    août 2009 modifié #6
    dans 1250494324:

    dans 1250491305:

    Dis moi si tu veux quand même que je les remette ici.

    Disons que j'aimerais que tu formules ta question de manière plus précise :
    • Qu'est-ce qui ne marche pas exactement, plantage ? non apparition de ce que tu attends ?
    • J'ai mis un NSLog() à  tel endroit dans le code (citer alors le code) et cela ne m'a pas donné ce que j'attendais,
    • J'en ai mis un autre ailleurs, et ...
    • ou j'ai lancé le debuggeur et il s'est passé tel chose ...

    En gros, la part d'analyse que tu as faite.

    Oki doki.
    Pour faire la sauvegarde, j'ai donc ajouté les méthodes d'archivage/désarchivage dans le GGPanel. Si je fous un point d'arrêt dans ces méthodes, je passe bien dedans.
    Ensuite, j'ai rajouté du code dans MyDocument.m (readFromData... et dataOfType). La encore, si je mets des points d'arrêts, je passe bien dedans.
    Lors de la sauvegarde, je génère un fichier avec des données dedans et notamment une couleur, ce qui me fait dire que la sauvegarde marche normalement.
    Par contre, le chargement ne fonctionne pas alors que je passe bien dans readDataFromType et initWithCoder. Je me demande si en fait il ne manque pas une intialisation du NSView quelque part dans le initWithCoder... Cela ne fonctionne par car rien ne s'affiche dans le NSView (GGPanel) : il est vierge. Mais je peux de nouveau dessiner dedans...
    A mon avis, le pb pourrait venir du
    <br />panel = [NSKeyedUnarchiver unarchiveObjectWithData:data];<br />
    

    Ca me fait bien passer dans initWithCoder de GGPanel, mais je pense que ça ne me permet pas de construire entièrement un panel, non?
    Merci :)

    EDIT : j'ai rajouté l'appel des méthodes des classes mères [super initWithCoder:decoder] et [super encodeWithCoder:encoder] mais ça ne change rien. De toutes façons, je pense qu'elles manquaient....
  • Philippe49Philippe49 Membre
    01:03 modifié #7
    Première hypothèse : il ne s'agirait pas de la même instance de GGPanel

    Mets un NSLog ainsi
    <br />NSLog(@&quot;%@&quot;,panel);&nbsp; // l&#39;IBOutlet dans le nib<br />panel = [NSKeyedUnarchiver unarchiveObjectWithData:data];<br />NSLog(@&quot;%@&quot;,panel); // la vue désarchivée par le data<br />
    

  • Philippe49Philippe49 Membre
    01:03 modifié #8
    dans 1250496459:


    Ca me fait bien passer dans initWithCoder de GGPanel, mais je pense que ça ne me permet pas de construire entièrement un panel, non?

    Pour construire une NSView, il vaut mieux avoir sa frame.
  • RadadaRadada Membre
    01:03 modifié #9
    dans 1250497925:

    dans 1250496459:


    Ca me fait bien passer dans initWithCoder de GGPanel, mais je pense que ça ne me permet pas de construire entièrement un panel, non?

    Pour construire une NSView, il vaut mieux avoir sa frame.

    Oki doki, mais comment la construire avec initWithCoder?
    Ou alors il faut que j'archive mon NSBezierPath et NSColor depuis le MyDocument et non depuis le GGPanel? Comme ça je construit un NSView et je lui redonne le path et la couleur? Il vaut mieux procéder ainsi?
    Merci :)
  • Philippe49Philippe49 Membre
    01:03 modifié #10
    dans 1250497205:

    Première hypothèse : il ne s'agirait pas de la même instance de GGPanel

    Mets un NSLog ainsi
    <br />NSLog(@&quot;%@&quot;,panel);&nbsp; // l&#39;IBOutlet dans le nib<br />panel = [NSKeyedUnarchiver unarchiveObjectWithData:data];<br />NSLog(@&quot;%@&quot;,panel); // la vue désarchivée par le data<br />
    


    Cela a donné quoi ?
  • Philippe49Philippe49 Membre
    01:03 modifié #11
    dans 1250498273:

    Oki doki, mais comment la construire avec initWithCoder?

    Dans la méthode d'archivage, on encode la frame.
    Dans la méthode de désarchivage, on décode ce NSRect et on l'affecte à  la frame de la vue.
    Il faut ensuite faire un addSubview pour installer la vue sur l'interface.

    dans 1250498273:

    Ou alors il faut que j'archive mon NSBezierPath et NSColor depuis le MyDocument et non depuis le GGPanel? Comme ça je construit un NSView et je lui redonne le path et la couleur? Il vaut mieux procéder ainsi?

    C'est une autre option, on archive le modèle plutôt qu'archiver la vue. Mais comme c'est un exercice, termine le premier choix et essaie ensuite le second.
  • mpergandmpergand Membre
    août 2009 modifié #12
    Je n'ai pas xcode3 donc je ne peux pas tester  ;)

    Mais, si je décompose ce qui se passe à  la création d'un document, il doit se passer ça:

    dans readFromData l'outlet panel n'est pas encore initialisé donc = nil

    panel = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    modifie l'adresse de l'outlet, mais représente une vue attachée dans le vide (pas de fenêtre) .

    de plus unarchiveObjectWithData retourne un object en autorelease .

    En fait l'outlet panel est initialisé dans windowControllerDidLoadNib.

    Donc effectivement tout ça a peu de chance de fonctionner.  :)

  • RadadaRadada Membre
    01:03 modifié #13
    dans 1250498708:

    dans 1250497205:

    Première hypothèse : il ne s'agirait pas de la même instance de GGPanel

    Mets un NSLog ainsi
    <br />NSLog(@&quot;%@&quot;,panel);&nbsp; // l&#39;IBOutlet dans le nib<br />panel = [NSKeyedUnarchiver unarchiveObjectWithData:data];<br />NSLog(@&quot;%@&quot;,panel); // la vue désarchivée par le data<br />
    


    Cela a donné quoi ?

    Le premier Log est Nil puisque l'objet n'est pas encore chargé et le second pointe sur un GGPanel...
  • RadadaRadada Membre
    01:03 modifié #14
    dans 1250498818:

    Dans la méthode d'archivage, on encode la frame.
    Dans la méthode de désarchivage, on décode ce NSRect et on l'affecte à  la frame de la vue.
    Il faut ensuite faire un addSubview pour installer la vue sur l'interface.


    Donc si j'ai bien suivi, dans encodeWithCoder, il faut faire un encodeObject: ForKeyPath: avec un [self frame].
    Dans initWithCoder, je désarchive la frame dans un NSRect, on fait un setFrame avec le NSRect, mais comment
    faire pour affecter la frame à  la vue? Et le addSubView, j'utilise quoi comme objet Vue???

    dans 1250498818:

    C'est une autre option, on archive le modèle plutôt qu'archiver la vue. Mais comme c'est un exercice, termine le premier choix et essaie ensuite le second.

    J'avais pas fait gaffe que ma Vue contenait le code du modèle. C'est étrange car c'est ce que Aaron Hilleglass fait dans le chapitre correspondant. Il vaut mieux utiliser un objet model qui contient le path et la couleur et ensuite les faire afficher sur la Vue? Mais dans ce cas là , il n'y a pas besoin de dériver la classe NSView non?

    Merci d'avance Philippe pour ton aide :)

    P.S. : idem pour l'annulation, si tu as une ou deux pistes, notamment sur l'affichage des NSBezierPath. Merci ;)
  • Philippe49Philippe49 Membre
    01:03 modifié #15
    dans 1250508961:

    dans 1250498708:

    dans 1250497205:

    Première hypothèse : il ne s'agirait pas de la même instance de GGPanel

    Mets un NSLog ainsi
    <br />NSLog(@&quot;%@&quot;,panel);&nbsp; // l&#39;IBOutlet dans le nib<br />panel = [NSKeyedUnarchiver unarchiveObjectWithData:data];<br />NSLog(@&quot;%@&quot;,panel); // la vue désarchivée par le data<br />
    


    Cela a donné quoi ?

    Le premier Log est Nil puisque l'objet n'est pas encore chargé et le second pointe sur un GGPanel...

    Commençons par la cause de tes ennuis. Dans la méthode -(IBAction)pickColor:(id)sender de AppController mets aussi NSLog(@%@",panel);


    Ensuite viendras la question, brutale mais nécessaire : Que fout AppController dans MyDocument.nib ? AppCOntroller est sensé contrôlé l'application et donc l'ensemble de tous les documents. Sa place est dans MainMenu.nib. 
    Cette méthode pickCOlor a sa place dans la classe MyDocument, représenté dans le xib par FIle's Owner.
  • Philippe49Philippe49 Membre
    août 2009 modifié #16
    dans 1250509340:

    dans 1250498818:

    C'est une autre option, on archive le modèle plutôt qu'archiver la vue. Mais comme c'est un exercice, termine le premier choix et essaie ensuite le second.

    J'avais pas fait gaffe que ma Vue contenait le code du modèle. C'est étrange car c'est ce que Aaron Hilleglass fait dans le chapitre correspondant. Il vaut mieux utiliser un objet model qui contient le path et la couleur et ensuite les faire afficher sur la Vue? Mais dans ce cas là , il n'y a pas besoin de dériver la classe NSView non?

    Dans les cas simples, on ne construit pas forcément les trois éléments du modèle MVC. Il est clair que la vue doit avoir le NSBezierPath et la couleur pour pouvoir se dessiner, et donc avoir des références à  ces valeurs,même si cela constitue le modèle. Mais les contenus de ses variables sont fournis par la couche model, le controller remplissant ce model en indiquant à  la vue de se rafraichir en conformité. Ce mécanisme est ici représenté par l'utilisateur dans l'exposé de ce chapitre, via la classe MyDocument, et directement par MyDocument dans le cas d'un archivage du modèle et non de la vue.

    Cependant, tu es parti sur l'archivage de la vue, ce n'est pas une sotte idée, car c'est ce que fait un nib. Termine sur cette piste, et aborde ensuite la seconde version.
  • Philippe49Philippe49 Membre
    01:03 modifié #17
    dans 1250509608:

    Commençons par la cause de tes ennuis. Dans la méthode -(IBAction)pickColor:(id)sender de AppController mets aussi NSLog(@%@",panel);


    ainsi que dans MyDocument, dans le load
    - (void)windowControllerDidLoadNib:(NSWindowController *) aController<br />{<br />&nbsp; &nbsp; [super windowControllerDidLoadNib:aController];<br />&nbsp; &nbsp; NSLog(@&quot;%@&quot;,panel);<br />......<br />
    
  • RadadaRadada Membre
    01:03 modifié #18
    dans 1250510732:

    dans 1250509608:

    Commençons par la cause de tes ennuis. Dans la méthode -(IBAction)pickColor:(id)sender de AppController mets aussi NSLog(@%@",panel);


    ainsi que dans MyDocument, dans le load
    - (void)windowControllerDidLoadNib:(NSWindowController *) aController<br />{<br />&nbsp; &nbsp; [super windowControllerDidLoadNib:aController];<br />&nbsp; &nbsp; NSLog(@&quot;%@&quot;,panel);<br />......<br />
    


    Effectivement, lors du chargement, ce ne sont pas les mêmes adresses....
    Je vais déplacer l'appController (pkoi l'ai-je mis dans MyDocument.xib, c'est un mystère...) et la suite et je te tiens au jus.
    Merci de ton aide en tout cas...
  • RadadaRadada Membre
    01:03 modifié #19
    dans 1250509608:

    Ensuite viendras la question, brutale mais nécessaire : Que fout AppController dans MyDocument.nib ? AppCOntroller est sensé contrôlé l'application et donc l'ensemble de tous les documents. Sa place est dans MainMenu.nib. 
    Cette méthode pickCOlor a sa place dans la classe MyDocument, représenté dans le xib par FIle's Owner.


    En fait, je n'ai absolument pas besoin d'un appController du coup non?
  • RadadaRadada Membre
    01:03 modifié #20
    dans 1250498818:


    Dans la méthode d'archivage, on encode la frame.
    Dans la méthode de désarchivage, on décode ce NSRect et on l'affecte à  la frame de la vue.
    Il faut ensuite faire un addSubview pour installer la vue sur l'interface.


    Alors, j'ai donc déplacé le pickColor dans MyDocument.m (qui me sert finalement de modèle non?).
    J'ai changé les méthodes suivantes selon ce que tu as préconisé qu dessus :
    <br />- (void)encodeWithCoder:(NSCoder *)encoder<br />{<br />&nbsp; &nbsp; [super encodeWithCoder:encoder];<br />&nbsp; &nbsp; [encoder encodeObject:color forKey:@&quot;color&quot;];<br />&nbsp; &nbsp; [encoder encodeObject:path forKey:@&quot;path&quot;];<br />&nbsp; &nbsp; [encoder encodeRect:[self frame] forKey:@&quot;frame&quot;];<br />}<br /><br />- (id)initWithCoder:(NSCoder *)decoder<br />{<br />&nbsp; &nbsp; // on appelle la méthode de la classe NSView qui gère le protocole NSCoding<br />&nbsp; &nbsp; [super initWithCoder:decoder];<br />&nbsp; &nbsp; // on récupère la frame<br />&nbsp; &nbsp; NSRect rect = [decoder decodeRectForKey:@&quot;frame&quot;];<br />&nbsp; &nbsp; // on l&#39;affecte<br />&nbsp; &nbsp; [self setFrame:rect];<br />&nbsp; &nbsp; // on appelle le constructeur de la vue mère<br />&nbsp; &nbsp; [self initWithFrame:rect];<br />&nbsp; &nbsp; // on décode les objets<br />&nbsp; &nbsp; color = [[decoder decodeObjectForKey:@&quot;color&quot;]retain];<br />&nbsp; &nbsp; path = [[decoder decodeObjectForKey:@&quot;path&quot;]retain];<br />&nbsp; &nbsp; return self;<br />}<br /><br />
    

    mais je ne vois vraiment pas quoi faire avec ça :
    dans 1250498818:

    Il faut ensuite faire un addSubview pour installer la vue sur l'interface.

    Dans le GGPanel, je ne vois pas quelle NSView passer et dans MyDocument, je ne vois pas non plus quoi passer... Des idées??? Merci chef ^^

  • Philippe49Philippe49 Membre
    01:03 modifié #21
    Mets
    • NSLog(@reading from data) dans la methode - (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
    • et NSLog(@loading form nib) dans windowControllerDidLoadNib:

    Tu vois  l'ordre dans lequel c'est appelé. C'est là  qu'il faut procéder à  l'échange du panel du nib avec le panel désarchivé.

    Les problèmes à  résoudre:
    • Tu as sans doute utilisé le même nom panel pour finalement deux objets différents. Cela va gêner, ne prends pas le même nom pour la vue créée dans readFromData et pour l'iBOutlet.
    • Il faut savoir retirer une vue de l'interface [oldView removeFromSuperview];
    • Rajouter une vue : [theSuperview addSubview:newView]
    • et un autre auquel tu peux répondre
  • mpergandmpergand Membre
    août 2009 modifié #22
    - (void)windowControllerDidLoadNib:(NSWindowController *) aController<br />{<br />&nbsp; &nbsp; [super windowControllerDidLoadNib:aController];<br />&nbsp; &nbsp; // Add any code here that needs to be executed once the windowController has loaded the document&#39;s window.<br />&nbsp; &nbsp; // on recharge le panneau une fois le fichier NIB chargé...<br />&nbsp; &nbsp; &nbsp; if(view!=nil)<br />		{<br />		NSRect frame=[panel frame];<br />		NSView* superview=[panel superview];<br />		[panel removeFromSuperview];<br />		[view setFrame:frame];<br />		[superview addSubview:view];<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [view release];<br />		panel=view;<br />		}<br />&nbsp; &nbsp; [panel setNeedsDisplay:YES];<br />}<br /><br />- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError<br />{<br />&nbsp; &nbsp; // Insert code here to write your document to data of the specified type. If the given outError != NULL, ensure that you set *outError when returning nil.<br /><br />&nbsp; &nbsp; // You can also choose to override -fileWrapperOfType:error:, -writeToURL:ofType:error:, or -writeToURL:ofType:forSaveOperation:originalContentsURL:error: instead.<br /><br />&nbsp; &nbsp; // For applications targeted for Panther or earlier systems, you should use the deprecated API -dataRepresentationOfType:. In this case you can also choose to override -fileWrapperRepresentationOfType: or -writeToFile:ofType: instead.<br /><br />&nbsp; &nbsp; if ( outError != NULL ) {<br />		*outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:unimpErr userInfo:NULL];<br />	}<br />&nbsp; &nbsp; // on renvoie simplement le panel archivé (appel de encodeWithCoder)<br />	return [NSKeyedArchiver archivedDataWithRootObject:panel];<br />}<br /><br />- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError<br />{<br />&nbsp; &nbsp; // Insert code here to read your document from the given data of the specified type.&nbsp; If the given outError != NULL, ensure that you set *outError when returning NO.<br /><br />&nbsp; &nbsp; // You can also choose to override -readFromFileWrapper:ofType:error: or -readFromURL:ofType:error: instead. <br />&nbsp; &nbsp; <br />&nbsp; &nbsp; // For applications targeted for Panther or earlier systems, you should use the deprecated API -loadDataRepresentation:ofType. In this case you can also choose to override -readFromFile:ofType: or -loadFileWrapperRepresentation:ofType: instead.<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; if ( outError != NULL ) {<br />		*outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:unimpErr userInfo:NULL];<br />	}<br />&nbsp; &nbsp; NSLog(@&quot;Lecture des données de type %@&quot;, typeName);<br />&nbsp; &nbsp; @try<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; view = [[NSKeyedUnarchiver unarchiveObjectWithData:data] retain];<br />&nbsp; &nbsp; }<br />&nbsp; &nbsp; @catch(NSException* e)<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; NSLog(@&quot;Exception %@&quot;, e);<br />&nbsp; &nbsp; &nbsp; &nbsp; if (outError)<br />&nbsp; &nbsp; &nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NSDictionary* d = [NSDictionary dictionaryWithObject:@&quot;Les données du fichier sont corromues&quot; forKey:NSLocalizedFailureReasonErrorKey];<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:unimpErr userInfo:d];<br />&nbsp; &nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; }<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; return YES;<br />}<br />
    


    j'ai ajouté une variable à  MyDocument.h
    @interface MyDocument : NSDocument
    {
        IBOutlet GGPanel* panel;
    NSView* view;
    }
    @end


    et voilà  ça marche !

    Mais c'est comme même n'importe quoi  ;D

  • Philippe49Philippe49 Membre
    01:03 modifié #23
    dans 1250515232:

    <br />- (id)initWithCoder:(NSCoder *)decoder<br />{<br />&nbsp; &nbsp; // on appelle la méthode de la classe NSView qui gère le protocole NSCoding<br />&nbsp; &nbsp; [super initWithCoder:decoder];<br />&nbsp; &nbsp; // on récupère la frame<br />&nbsp; &nbsp; NSRect rect = [decoder decodeRectForKey:@&quot;frame&quot;];<br />&nbsp; &nbsp; // on l&#39;affecte<br />&nbsp; &nbsp; [self setFrame:rect];<br />&nbsp; &nbsp; // on appelle le constructeur de la vue mère<br />&nbsp; &nbsp; [self initWithFrame:rect];<br />&nbsp; &nbsp; // on décode les objets<br />&nbsp; &nbsp; color = [[decoder decodeObjectForKey:@&quot;color&quot;]retain];<br />&nbsp; &nbsp; path = [[decoder decodeObjectForKey:@&quot;path&quot;]retain];<br />&nbsp; &nbsp; return self;<br />}<br />
    



    La ligne  [self initWithFrame:rect]; n'est pas à  mettre, on n'initialise pas deux fois !
  • Philippe49Philippe49 Membre
    01:03 modifié #24
    Dans windowControllerDidLoadNib:, le [panel setNeedsDisplay:YES]; est fait implicitement lors du addSubview:, il ne devrait donc pas être nécessaire.
  • RadadaRadada Membre
    01:03 modifié #25
    Merci, mais je vais essayer comme propose Philippe, c.a.d. en me démerdant avec un peu d'aide quand même :) :)
  • Philippe49Philippe49 Membre
    01:03 modifié #26
    Bon je déplace ce sujet vers la rubrique débutants ...
  • RadadaRadada Membre
    01:03 modifié #27
    dans 1250534217:

    Bon je déplace ce sujet vers la rubrique débutants ...

    lol oki doki.
    J'ai réussi à  afficher de que j'avais dans le fichier de sauvergade mais j'ai un planton maitenant avec une adresse à  0x00, il faut que je creuse...
    Je te tiens au jus. Merci de ton aide en tout cas :)
  • RadadaRadada Membre
    01:03 modifié #28
    dans 1250534217:

    Bon je déplace ce sujet vers la rubrique débutants ...


    Etrange comportement. Je recharge bien toutes les données, mais tant que je ne cliques pas dans la frame, elle ne se rafraichit pas...
    Pour info, j'ai pondu le code d'après tes indications, je ne l'ai pas pompé de mpergand

    <br />Dans le MyDocument.h j&#39;ai rajouté un GGPanel* loadedPanel;<br /><br />- (void)windowControllerDidLoadNib:(NSWindowController *) aController<br />{<br />&nbsp; &nbsp; [super windowControllerDidLoadNib:aController];<br />&nbsp; &nbsp; // Add any code here that needs to be executed once the windowController has loaded the document&#39;s window.<br />&nbsp; &nbsp; NSLog(@&quot;windowControllerDidLoadNib %@ %@&quot;,panel, loadedPanel); // la vue désarchivée par le data<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; if (loadedPanel)<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; // on récupère la supervue du panel du Nib<br />&nbsp; &nbsp; &nbsp; &nbsp; NSView* panelSuperView = [panel superview];<br />&nbsp; &nbsp; &nbsp; &nbsp; // on supprime le panel du nib de la supervue<br />&nbsp; &nbsp; &nbsp; &nbsp; [panel removeFromSuperview];<br />&nbsp; &nbsp; &nbsp; &nbsp; // le panel est maintenant celui chargé à  partir du fichier de sauvegarde<br />&nbsp; &nbsp; &nbsp; &nbsp; panel = loadedPanel;<br />&nbsp; &nbsp; &nbsp; &nbsp; // on rajoute ce panel à  la supervue<br />&nbsp; &nbsp; &nbsp; &nbsp; [panelSuperView addSubview:panel];<br />&nbsp; &nbsp; &nbsp; &nbsp; // on modifie la couleur du colorWell<br />&nbsp; &nbsp; &nbsp; &nbsp; [colorWell setColor:[panel color]];<br />&nbsp; &nbsp; &nbsp; &nbsp; // on affiche les données<br />&nbsp; &nbsp; &nbsp; &nbsp; [panel setNeedsDisplay:YES];<br />&nbsp; &nbsp; &nbsp; &nbsp; [loadedPanel setNeedsDisplay:YES];<br />&nbsp; &nbsp; }<br />&nbsp; &nbsp; else<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; [colorWell setColor:[NSColor redColor]];<br />&nbsp; &nbsp; &nbsp; &nbsp; [panel setColor:[colorWell color]];<br />&nbsp; &nbsp; }<br />&nbsp; &nbsp; NSLog(@&quot;après windowControllerDidLoadNib %@ %@&quot;,panel, loadedPanel); // la vue désarchivée par le data<br />}<br /><br />- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError<br />{<br />&nbsp; &nbsp; // Insert code here to read your document from the given data of the specified type.&nbsp; If the given outError != NULL, ensure that you set *outError when returning NO.<br /><br />&nbsp; &nbsp; // You can also choose to override -readFromFileWrapper:ofType:error: or -readFromURL:ofType:error: instead. <br />&nbsp; &nbsp; <br />&nbsp; &nbsp; // For applications targeted for Panther or earlier systems, you should use the deprecated API -loadDataRepresentation:ofType. In this case you can also choose to override -readFromFile:ofType: or -loadFileWrapperRepresentation:ofType: instead.<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; if ( outError != NULL ) {<br />		*outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:unimpErr userInfo:NULL];<br />	}<br />&nbsp; &nbsp; NSLog(@&quot;Lecture des données de type %@&quot;, typeName);<br />&nbsp; &nbsp; @try<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; loadedPanel = [[NSKeyedUnarchiver unarchiveObjectWithData:data] retain];;<br />&nbsp; &nbsp; }<br />&nbsp; &nbsp; @catch(NSException* e)<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; NSLog(@&quot;Exception %@&quot;, e);<br />&nbsp; &nbsp; &nbsp; &nbsp; if (outError)<br />&nbsp; &nbsp; &nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NSDictionary* d = [NSDictionary dictionaryWithObject:@&quot;Les données du fichier sont corromues&quot; forKey:NSLocalizedFailureReasonErrorKey];<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:unimpErr userInfo:d];<br />&nbsp; &nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; }<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; return YES;<br />}<br />
    


    Des idées par hasard svp?

    Autre truc étrange, si je fais un [panel release] juste après le removeFromSuperView, ça me fait planter l'appli... Une idée également? Peut être parce qu'un OUTLET n'est jamais nil ou ne peut pas l'être?

    Et enfin dernièrement : est-ce que je peux implémenter un mécanisme d'annulation tel quel? Je ne vois pas vraiment comment sachant qu'il n'existe pas de méthode qui supprime une forme d'un NSBezierPath non?

    Merci d'avance de tes réponses. :)
  • mpergandmpergand Membre
    01:03 modifié #29
    dans 1250587999:

    Autre truc étrange, si je fais un [panel release] juste après le removeFromSuperView, ça me fait planter l'appli... Une idée également? Peut être parce qu'un OUTLET n'est jamais nil ou ne peut pas l'être?


    C'est normal le panel est releasé par removeFromSuperView.
    Ce qu'il faut faire c'est:
    [loadedPanel release];

    car il est retenu 2 fois, une fois par [[NSKeyedUnarchiver unarchiveObjectWithData:data] retain]
    et une fois lors de l'ajout par addSubview.
  • Philippe49Philippe49 Membre
    01:03 modifié #30
    dans 1250587999:

    Peut être parce qu'un OUTLET n'est jamais nil ou ne peut pas l'être?

    Il ne faut pas croire que faire [panel release] avec par la suite un dealloc fait que panel=nil. Le dealloc désalloue la zone pointée par panel, la rendant réutilisable pour d'autres instances, mais panel garde sa référence à  cette zone mémoire.

    Expérience:
    #import &lt;Foundation/Foundation.h&gt;<br /><br />int main (int argc, const char * argv&#91;]) {<br />	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];<br />	NSString * string=[[NSString alloc] initWithFormat:@&quot;Coucou %d fois&quot;,1];<br />	[string release];<br />	if(string!=nil) {<br />		NSLog(@&quot;string pointe sur : %p&quot;,string);<br />		NSLog(@&quot;qui vaut encore : %@&quot;,string);		<br />	}<br />	[pool drain];<br />	return 0;<br />}<br />
    


    L'exécution montre que string n'est pas nil, et que le contenu de la mémoire pointée sur le tas a été remplacée ici par la chaà®ne utilitaire @qui vaut encore : (évidemment le contenu de l'adresse est indéterminée, on ne peut pas savoir ce qu'il y aura à  l'exécution)

    % gcc pgm.m -o pgm -std=c99 -framework Foundation
    % pgm
    2009-08-18 12:18:16.506 pgm[716:10b] string pointe sur : 0x105470
    2009-08-18 12:18:16.507 pgm[716:10b] qui vaut encore : qui vaut encore :
    %
  • RadadaRadada Membre
    01:03 modifié #31
    dans 1250589687:

    dans 1250587999:

    Autre truc étrange, si je fais un [panel release] juste après le removeFromSuperView, ça me fait planter l'appli... Une idée également? Peut être parce qu'un OUTLET n'est jamais nil ou ne peut pas l'être?


    C'est normal le panel est releasé par removeFromSuperView.
    Ce qu'il faut faire c'est:
    [loadedPanel release];

    car il est retenu 2 fois, une fois par [[NSKeyedUnarchiver unarchiveObjectWithData:data] retain]
    et une fois lors de l'ajout par addSubview.


    J'avais hésité à  faire ça, mais j'ai encore trop de réflexes C++. J'avais peur que ça vide la zone mémoire complètement : )
    Merci :p
Connectez-vous ou Inscrivez-vous pour répondre.