NSArray : données qui se dupliquent ou qui disparaissent

VeillardVeillard Membre
18:28 modifié dans API AppKit #1
Bonjour,

J'ai un petit problème à  vous soumettre :

Dans mon appli, je crée une liste de plongée sous forme d'Array de Dict
Chaque item du Dict correspond à  une plongée où on trouve différents les paramètres de la plongée.
Ma liste de plongées est affichée sous forme d'une TableView.
J'ai récemment inclus dans les Dict d'autres paramètres correspondant à  mes profils de plongées qui sont en fait des Array.
Bon, je vais résumer :

<array> //  root
<dict>   //  une plongée
<string> // lieu
<string> // site
....     // etc...
<array> // profil (profondeur)
<array> // profil (alarme palier)
<array> // profil (alarme vitesse)
</dict>
</array>

Voilà , à  chaque fois que j'ajoute ou que j'insère une plongée dans ma liste, les 3 Arrays de la plongée créée contiennent les données de la plongée précédente.
J'ai essayé de vider les Arrays à  chaque fois que je créée une plongée avec :

<br />	[profilProfondeur removeAllObjects];<br />	[ASC_Flag removeAllObjects];<br />	[SLOW_Flag removeAllObjects];<br />	[profilProfondeur addObject: [NSNumber numberWithDouble:0.0]];<br />	[ASC_Flag addObject: [NSNumber numberWithInt:0]];<br />	[SLOW_Flag addObject: [NSNumber numberWithInt:0]];<br />

:why?:
le problème, c'est que les données de la plongée précédente sont eux aussi effacées. Ce que je ne comprend pas, c'est que ça ne touche pas les autres objets du type String, Number...

D'où cela peut-il venir ?

Réponses

  • mpergandmpergand Membre
    18:28 modifié #2
    Salut!

    le problème, c'est que les données de la plongée précédente sont eux aussi effacées.


    Logique, tu manipules le même pointeur. Le problème est en amont, quand tu initialises la nouvelle plongée, tu dois utiliser les tableaux du profil en cours ou un truc du genre. Vérifie que tu initialises bien correctement ces tableaux de profils ;)
  • VeillardVeillard Membre
    18:28 modifié #3
    Hello

    J'ai rajouté
    profilProfondeur = [[NSMutableArray alloc] init];<br />		ASC_Flag = [[NSMutableArray alloc] init];<br />		SLOW_Flag = [[NSMutableArray alloc] init];<br />
    


    dans : - (id)init et rien n'a changé  :'(
    J'initialise mes données à  chaque nouvelle plongée avec ceci :

    - (IBAction)blankFields:(id)sender<br />{<br />	NSCalendarDate&nbsp; *now;<br />	now = [NSCalendarDate calendarDate];<br /><br />	[plongeeNoField setStringValue:@&quot;&quot;];<br />	[dateField setObjectValue:now];<br />	[heureField setObjectValue:now];<br />	[coeffField setStringValue:@&quot;-&quot;];<br />	[pmBmPopUp selectItemAtIndex:0];<br />	[lieuField setStringValue:@&quot;&quot;];<br />	[siteField setStringValue:@&quot;&quot;];<br />	...<br />	[profilProfondeur removeAllObjects];<br />	[ASC_Flag removeAllObjects];<br />	[SLOW_Flag removeAllObjects];<br />	[profilProfondeur addObject: [NSNumber numberWithDouble:0.0]];<br />	[ASC_Flag addObject: [NSNumber numberWithInt:0]];<br />	[SLOW_Flag addObject: [NSNumber numberWithInt:0]];<br />}<br />
    


    Quand je clique sur une nouvelle plongée j'appelle l'initialisation comme ceci :
    - (IBAction)newDive:(id)sender<br />{<br />	[editWindow makeKeyAndOrderFront:nil];<br />	<br />	[self blankFields:nil];<br />	...<br />	[self updateUI:nil];<br />}<br />
    


    Est-ce la bonne technique ?
  • mpergandmpergand Membre
    décembre 2004 modifié #4
    Donc, les variables que tu initialises dans blankFields appartiennent au contrôleur, lorsque tu crées une nouvelle plongée, donc tu initialises les mêmes variables.

    Lorsque tu fais:
    [profilProfondeur removeAllObjects];

    tu utilises toujours le même objet (pointeur). Quand tu sauvegardes une plongée, tu crées une copie de ces objets ? sinon il y a de fortes chances pour que toutes les plongées partagent le même objet !

    dans : - (id)init et rien n'a changé


    init du contrôleur ? appellé une seule fois à  la création du document ?
  • VeillardVeillard Membre
    18:28 modifié #5
    lorsque tu crées une nouvelle plongée, donc tu initialises les mêmes variables.

    C'est tout à  fait ce qui se passe

    Quand tu sauvegardes une plongée, tu crées une copie de ces objets ?

    Justement, quand je sauvegarde, je peux modifier la dernière plongée dans que la précédente soit modifiée, ceci à  condition de fermer et de réouvrir mon document.

    init du contrôleur ? appellé une seule fois à  la création du document ?

    Oui
  • mpergandmpergand Membre
    décembre 2004 modifié #6
    dans 1102596263:

    init du contrôleur ? appellé une seule fois à  la création du document ?

    Oui


    Donc pour chaque nouvelle plongée c'est le même objet profilPronfondeur, dans blankFields essaye:
    [profilProfondeur release]; // libère l'ancien profil ( au démarrage créé dans init du contrôleur ? )
    profilProfondeur = [[NSMutableArray alloc] init];
  • VeillardVeillard Membre
    18:28 modifié #7
    J'avais déjà  essayé => plantage (SIGBUS)  :'(

    Pour info, les trois tableaux ont des accesseurs, ça peut peut-être venir de là  ?
  • mpergandmpergand Membre
    18:28 modifié #8
    Récapitulons !

    - création de profilPronfondeur dans init du contrôleur -> count =1
    - sauvegarde du profil setObject: profil forKey: ... ->count =2
    - création nouveau profil [ profilProfondeur release] -> count=1 ou 0 si pas de sauvegarde

    conclusion: ça peut pas planter :)

    enfin si tu fais comme ça ;D
  • VeillardVeillard Membre
    18:28 modifié #9
    En fait, dès que je fais un "release", ça plante  :(

    J'ai essayé de débugger, ça me met ceci :
    0x908311e0&nbsp; &lt;+0000&gt;&nbsp; cmplwi	r3,0<br />0x908311e4&nbsp; &lt;+0004&gt;&nbsp; beq-	0x90831308 &lt;objc_msgSend+296&gt;<br />0x908311e8&nbsp; &lt;+0008&gt;&nbsp; lwz	r12,0(r3)<br />0x908311ec&nbsp; &lt;+0012&gt;&nbsp; lwz	r12,32(r12)<br />0x908311f0&nbsp; &lt;+0016&gt;&nbsp; stw	r9,48(r1)<br />0x908311f4&nbsp; &lt;+0020&gt;&nbsp; lwz	r11,0(r12)<br />0x908311f8&nbsp; &lt;+0024&gt;&nbsp; addi	r9,r12,8<br />
    

    J'y comprends rien ???
    Par contre, j'ai :
    0 objc_msgSend<br />1 -[Carnet dealloc]
    
  • mpergandmpergand Membre
    18:28 modifié #10
    ???

    et dans le crash log ça dit quoi ?
  • VeillardVeillard Membre
    18:28 modifié #11
    Ceci :
    Executable “Plongée” has exited due to signal 10 (SIGBUS)

    J'ai un accesseur :
    [profilView setProfilData: profilProfondeur];
    

    Ca peut peut-être interférer, sinon, je ne vois pas  ???

  • VeillardVeillard Membre
    18:28 modifié #12
    Si ça peut aider...
    [Switching to process 797 local thread 0x1107]
    Running...
    Program received signal:  "EXC_BAD_ACCESS".
    (gdb)
  • 18:28 modifié #13
    dans 1102612571:

    Ceci :
    Executable ?Plongée? has exited due to signal 10 (SIGBUS)

    J'ai un accesseur :
    [profilView setProfilData: profilProfondeur];
    

    Ca peut peut-être interférer, sinon, je ne vois pas ???


    Quel est le code que tu mets dans cet accesseur? Si tu fais par exemple (myData étant la variable d'instance):

    -(void)setData:(NSData*)data {<br />	[myData release];<br />	myData = [data retain];<br />}
    


    ça peut planter dans le cas où myData == data (autrement dit si c'est le même objet, à  ne pas confondre avec [data isEqualToData:myData], qui peut renvoyer TRUE si on a affaire à  deux objets différents, mais contenant des variables semblables). Si c'est comme ça, deux solutions: [myData autorelease] au lieu du release, ou passer par une variable temporaire:
    -(void)setData:(NSData*)data {<br />	id oldData = myData;<br />	myData = [data retain];<br />	[oldData release];<br />}
    
  • VeillardVeillard Membre
    18:28 modifié #14
    Salut Renaud,

    ça peut planter dans le cas où myData == data

    C'était effectivement le cas (erreur de débutant  :o )

    Par contre, j'ai toujours mon objet partagé. Maintenant, j'ai pourtant :
    - (id)init<br />{<br />&nbsp; &nbsp; self = [super init];<br />&nbsp; &nbsp; if (self)<br />	{<br />		tableauDesPlongees = [[NSMutableArray alloc] init];<br />		<br />		profilProfondeur = [[NSMutableArray alloc] init];<br />		ASC_Flag = [[NSMutableArray alloc] init];<br />		SLOW_Flag = [[NSMutableArray alloc] init];<br />	}<br />&nbsp; &nbsp; return self;<br />}<br /><br />- (void)dealloc<br />{<br />	[tableauDesPlongees release];<br /><br />	[profilProfondeur release];<br />	[ASC_Flag release];<br />	[SLOW_Flag release];<br />}<br />
    


    Quand je fais :
    <br />- (IBAction)blankFields:(id)sender<br />{<br />	[profilProfondeur release];<br />	profilProfondeur = [[NSMutableArray alloc] init];<br />	[profilProfondeur addObject: [NSNumber numberWithDouble:0.0]];<br />	[ASC_Flag release];<br />	ASC_Flag = [[NSMutableArray alloc] init];<br />	[ASC_Flag addObject: [NSNumber numberWithInt:0]];<br />	[SLOW_Flag release];<br />	SLOW_Flag = [[NSMutableArray alloc] init];<br />	[SLOW_Flag addObject: [NSNumber numberWithInt:0]];<br />}<br />
    

    la plongée ajoutée a les 3 tableaux vierges, quand je clique sur la plongée précédents => plantage et 2 plongées avant => ok

    Si je fais :
    - (IBAction)blankFields:(id)sender<br />{<br />	[profilProfondeur removeAllObjects];<br />	[ASC_Flag removeAllObjects];<br />	[SLOW_Flag removeAllObjects];<br />	[profilProfondeur addObject: [NSNumber numberWithDouble:0.0]];<br />	[ASC_Flag addObject: [NSNumber numberWithInt:0]];<br />	[SLOW_Flag addObject: [NSNumber numberWithInt:0]];<br />}<br />
    

    la plongée ajoutée contient des tebleaux vierges et efface toujours celle d'avant  :'(
  • mpergandmpergand Membre
    décembre 2004 modifié #15
    ça peut planter dans le cas où myData == data


    pourquoi utiliser NSData ?

    pourquoi ne pas communiquer le tableau à  profilView:

    <br />NSArray* profilArray;<br /><br />....<br /><br />-(void) setProfilData: (NSArray*)profilProfondeur<br />{<br />profilArray=profilProfondeur;<br /><br />}<br />
    


    Mais il me semble que tu as déjà  eu un problème similaire avec les plongées, tu gère les données de plongées différemment des données de profils ?


    la plongée ajoutée a les 3 tableaux vierges, quand je clique sur la plongée précédents => plantage et 2 plongées avant => ok


    Tu sembles utiliser les objets de la fiche prédédemment affichée et comme ils ont étés libérés ...

    Je pense que tu ne sauvegarde pas les bons objets dans le plist, ou alors les pointeurs ont été modifiés entre temps (profilView ?)

    Et regarde auusi dans le fichier:
    ~/Library/logs/CrashReporter/Plongée.crash.log
  • VeillardVeillard Membre
    18:28 modifié #16
    pourquoi utiliser NSData ?

    C'était un exemple. J'utilise NSMutableArray à  la place.

    NSMutableArray* profilArray;<br /><br />....<br /><br />-(void) setProfilData: (NSMutableArray*)profilProfondeur<br />{<br />profilArray=profilProfondeur;<br /><br />}
    


    C'est en effet ce qu'on avait fait. Le seul problème, c'est quand je fais un "release", ça plante  B)

    C'est pour ça, que j'ai utilisé la méthode de Renaud pour résoudre ce problème de "release"

    Mais le problème de "partage" persiste...  :-\\
  • mpergandmpergand Membre
    18:28 modifié #17
    C'est pour ça, que j'ai utilisé la méthode de Renaud pour résoudre ce problème de "release"


    Je pense que ça cache le vrai problème, la vérité est ailleurs :-*
  • VeillardVeillard Membre
    18:28 modifié #18
    Je sens que ça ne va pas être simple  :crackboom:-
  • mpergandmpergand Membre
    18:28 modifié #19
    On peut prendre le problème autrement:

    Tu supprimes tous les release/init dans blankFields, mais lorsque tu sauvegarde s dans le plist tu crées une copie:

    NSMutableArray* copie=[profilProfondeur clone]; // ou autre méthode, j'suis pas sûr
    [dic setObject: copie forKey: clef];
    [copie release]; // ?

    mon code est peut-être pas bon, c'est juste une idée :P
  • VeillardVeillard Membre
    18:28 modifié #20
    NSMutableArray* copie=[profilProfondeur clone]; // ou autre méthode, j'suis pas sûr


    Ca doit être :
    NSMutableArray *clone = [profilProfondeur copy];
    


    Que se passe-t-il si la personne créée des plongées à  la volée sans enregistrer à  chaque fois  ???

    Je vais essayer ce soir à  la maison  :P
  • 18:28 modifié #21
    dans 1102666461:

    <br />- (void)dealloc<br />{<br />	[tableauDesPlongees release];<br /><br />	[profilProfondeur release];<br />	[ASC_Flag release];<br />	[SLOW_Flag release];<br />}<br />
    


    ça ne résoudra pas ton problème, mais il y a une grosse fuite mémoire là ... Il ne faut pas oublier de terminer les dealloc par [super dealloc]; sinon l'objet n'est pas viré de la mémoire...
  • VeillardVeillard Membre
    18:28 modifié #22
    Il ne faut pas oublier de terminer les dealloc par [super dealloc]; sinon l'objet n'est pas viré de la mémoire...


    J'avais oublié...  :o
    Merci Renaud
Connectez-vous ou Inscrivez-vous pour répondre.