NSCoding et Outlets

MickMick Membre
avril 2011 modifié dans API AppKit #1
Bonjour à  tous,

Je me prends un peu la tête avec ces histoires de NSCoding... J'ai une document-based application. J'ai implémenté initWithCoder et encodeWithCoder dans ma subclass de MyDocument. Les variables d'instances de MyDocument sont bien initialisées sans soucis... Sauf que, j'ai différents controleurs, instances de sous-classes NSObject, qui sont instanciés via interface builder. J'ai donc des outlets dans MyDocument qui pointent vers ces controleurs. J'aimerais initialiser correctement les variables d'instances de ces controleurs lors de l'ouverture d'un fichier. Pour cela, j'ai implémenté initWithCoder et encodeWithCoder pour toutes les classes concernées.

Au debug, le controleur est bien initialisé, puis juste après il est désalloué... Le problème vient a priori du fait que lorsque je désarchive mon fichier, tout est bien initialisé... Mais, une fois cela fait, le fichier NIB est désarchivé, et de ce fait, des nouvelles instances toutes fraà®ches sont allouées et initialisées "à  zéro" ...

Comment faire donc pour initialiser les variables d'instances d'objets créés dans IB ?

Si ce n'est pas possible, comment puis-je faire pour "connecter" les outlets si j'instancie via le code ? Faut-il que j'en déduise que MyDocument doit contenir TOUS les outlets ?

Voici un bout de code : ici le controleur de graphes, qui est instancié via IB
<br />@implementation ControleurGraphes<br />- (void)encodeWithCoder:(NSCoder *)leCodeur {<br />	[leCodeur encodeObject:parametresAxes forKey:@&quot;parametresAxes&quot;];<br />	[leCodeur encodeObject:tangentes forKey:@&quot;tangentes&quot;];<br />	[leCodeur encodeObject:xAxis forKey:@&quot;xAxis&quot;];<br />	[leCodeur encodeObject:reticule forKey:@&quot;reticule&quot;];<br />}<br />- (id)initWithCoder:(NSCoder *)leCodeur {<br />	self=[super init];<br />	parametresAxes=[[leCodeur decodeObjectForKey:@&quot;parametresAxes&quot;] retain];<br />	tangentes=[[leCodeur decodeObjectForKey:@&quot;tangentes&quot;] retain];<br />	reticule=[[NSMutableDictionary dictionaryWithObjectsAndKeys:<br />			&nbsp;  [NSNumber numberWithBool:NO],@&quot;hasFirstPoint&quot;,<br />			&nbsp;  [NSNumber numberWithBool:NO],@&quot;hasSecondPoint&quot;,nil] retain];<br />	leMode=selection;<br />	xAxis=[leCodeur decodeObjectForKey:@&quot;xAxis&quot;];<br />	return self;<br />}<br />

Le bout de code de MyDocument :
<br />- (id)initWithCoder:(NSCoder *)leCodeur {<br />	self=[super init];<br />	lesFlags=[[leCodeur decodeObjectForKey:@&quot;lesFlags&quot;] retain];<br />	lesPointsDeReglages=[[leCodeur decodeObjectForKey:@&quot;lesPointsDeReglages&quot;] retain];<br />	listeDesVars=[[leCodeur decodeObjectForKey:@&quot;listeDesVars&quot;] retain];<br />	listeDerivatedVars=[[leCodeur decodeObjectForKey:@&quot;listeDerivatedVars&quot;] retain];<br />	newID=[leCodeur decodeIntForKey:@&quot;newID&quot;];<br />	lesDonnees=[[leCodeur decodeObjectForKey:@&quot;lesDonnees&quot;] retain];<br />	lesGraphes=[[leCodeur decodeObjectForKey:@&quot;lesGraphes&quot;] retain];<br />	urlFilmOuImage=[[leCodeur decodeObjectForKey:@&quot;urlFilmOuImage&quot;] retain];<br />	leControleurGraphes=[leCodeur decodeObjectForKey:@&quot;leControleurGraphes&quot;];<br />	return self;<br />}<br />- (void)encodeWithCoder:(NSCoder *)leCodeur {<br />	[leCodeur encodeObject:leControleurGraphes forKey:@&quot;leControleurGraphes&quot;];<br />	[leCodeur encodeObject:lesFlags forKey:@&quot;lesFlags&quot;];<br />	[leCodeur encodeObject:lesPointsDeReglages forKey:@&quot;lesPointsDeReglages&quot;];<br />	[leCodeur encodeObject:listeDesVars forKey:@&quot;listeDesVars&quot;];<br />	[leCodeur encodeObject:listeDerivatedVars forKey:@&quot;listeDerivatedVars&quot;];<br />	[leCodeur encodeInt:newID forKey:@&quot;newID&quot;];<br />	[leCodeur encodeObject:lesDonnees forKey:@&quot;lesDonnees&quot;];<br />	[leCodeur encodeObject:lesGraphes forKey:@&quot;lesGraphes&quot;];<br />	[leCodeur encodeObject:urlFilmOuImage forKey:@&quot;urlFilmOuImage&quot;];<br />}<br />- (id)initWithContentsOfURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError {<br />	self=[NSKeyedUnarchiver unarchiveObjectWithFile:[absoluteURL path]];<br />	return self;<br />}<br />

Réponses

  • laudemalaudema Membre
    avril 2011 modifié #2
    Mettre ton code dans un méthode awakeFromNib qui est appelée quand un objet est chargé serait peut être plus efficace ?
    <br />- (void)awakeFromNib{<br />&nbsp; &nbsp; //initialisation des variables, l&#039;objet est déjà  créé<br />}
    

    éveil des objets du nib
  • MickMick Membre
    11:48 modifié #3
    Bonjour Laudéma,

    Je ne vois pas comment procéder. En effet, la méthode initWithCoder: est appelée avant awakeFromNib. Je n'ai accès au coder que dans cette méthode pour décoder les objets.... je ne comprends pas la logique de cette histoire de coder !! Lors de l'ouverture du fichier, la méthode readFromURL, ou dataOfType ... est appelée : c'est bien dans cette méthode qu'il faut appeler [NSKeyedUnarchiver unarchiveObjectWithFile:] ? Après cela, les méthodes initWithCoder sont appelées pour chaque objet du graph, et ensuite awakeFromNib... qui écrase tout pour les objets qui sont instanciés dans IB !!

    Comment désarchiver les objets dans awakeFromNib ?
  • CéroceCéroce Membre, Modérateur
    11:48 modifié #4
    Je ne comprends pas trop ce que tu essaies de faire, mais il est étrange de vouloir implémenter NSCoding sur des contrôleurs. Ce sont les objets de la couche "modèle" qui doivent implémenter ce protocole.
  • MickMick Membre
    11:48 modifié #5
    Effectivement, j'ai "repensé" l'appli et lui ai donné une "couche données". Du coup j'encode un dictionnaire qui contient toutes les données, et affecte les variables d'instances à  partir de cela et ça fonctionne. En fait, je n'ai pas bien pensé la couche "donnée" et ai un peu mélangé données et controleurs.

    Ca m'apprendra !

    Merci pour vos réponses en tout cas. Voici les bouts de codes. Si vous voyez des horreurs, dites-le moi !
    <br />// Dans writeToUrl: de MyDocument<br />if ([type isEqualToString:@&quot;Document VallPoint&quot;]) {<br />		leModele=[NSDictionary dictionaryWithObjectsAndKeys:<br />				&nbsp; listeDesVars,@&quot;listeDesVars&quot;,<br />				&nbsp; listeDerivatedVars,@&quot;listeDerivatedVars&quot;,<br />				&nbsp; lesDonnees,@&quot;lesDonnees&quot;,<br />				&nbsp; lesGraphes,@&quot;lesGraphes&quot;,<br />				&nbsp; lesPointsDeReglages,@&quot;lesPointsDeReglages&quot;,<br />				&nbsp; lesFlags,@&quot;lesFlags&quot;,<br />				&nbsp; [NSNumber numberWithInt:newID],@&quot;newID&quot;,<br />				&nbsp; parametresAxes,@&quot;parametresAxes&quot;,<br />				&nbsp; reticule,@&quot;reticule&quot;,<br />				&nbsp; tangentes,@&quot;tangentes&quot;,<br />				&nbsp; urlFilmOuImage,@&quot;urlFilmOuImage&quot;,<br />				&nbsp; xAxis,@&quot;xAxis&quot;,nil];<br />		ok=[NSKeyedArchiver archiveRootObject:leModele toFile:[absoluteURL path]];<br />	}<br />
    

    <br />//Dans readFromURL:<br />leModele=[NSKeyedUnarchiver unarchiveObjectWithFile:[absoluteURL path]];<br />		listeDesVars=[[leModele objectForKey:@&quot;listeDesVars&quot;] retain];<br />		listeDerivatedVars=[[leModele objectForKey:@&quot;listeDerivatedVars&quot;] retain];<br />		lesDonnees=[[leModele objectForKey:@&quot;lesDonnees&quot;] retain];<br />		lesGraphes=[[leModele objectForKey:@&quot;lesGraphes&quot;] retain];<br />		lesPointsDeReglages=[[leModele objectForKey:@&quot;lesPointsDeReglages&quot;] retain];<br />		lesFlags=[[leModele objectForKey:@&quot;lesFlags&quot;] retain];<br />		newID=[[leModele objectForKey:@&quot;newID&quot;] intValue];<br />		parametresAxes=[[leModele objectForKey:@&quot;parametresAxes&quot;] retain];<br />		reticule=[[leModele objectForKey:@&quot;reticule&quot;] retain];<br />		tangentes=[[leModele objectForKey:@&quot;tangentes&quot;] retain];<br />		urlFilmOuImage=[[leModele objectForKey:@&quot;urlFilmOuImage&quot;] retain];<br />		xAxis=[[leModele objectForKey:@&quot;xAxis&quot;] retain];<br />
    
  • HerveHerve Membre
    11:48 modifié #6
    On peut associer les contrôleurs dans IB à  des variables avec des liaisons (sous menu "blind" dans l'inspecteur de l'objet : tu relies à  la classe, puis à  la variable). Dans ce cas, une fois que "initWithCoder" aura rappelé les variables, les sliders et autres contrôles se mettront en place tout seuls. No?? ;)
Connectez-vous ou Inscrivez-vous pour répondre.