NSMutableArray récalcitrant

VeillardVeillard Membre
15:48 modifié dans API AppKit #1
Bonjour,

J'ai un Array "profilProfondeur" déclaré en global. Dans cet array, je stocke un profil de plongée.
Deux fichiers : Carnet.m et Profil.m utilisent le même array. Lorsque je clique sur une des plongées dans ma TableView, j'arrive à  afficher mon profil puis lorsque je clique sur la plongée suivante, le même profil reste affiché.  :'(
- (IBAction)handlePlongeeClick:(id)sender<br />{<br />&nbsp; &nbsp; currentIndex = [sender selectedRow];<br />	if (currentIndex == -1) return;<br />		<br />&nbsp; &nbsp; profilProfondeur = [[NSMutableArray arrayWithArray:[[tableauDesPlongees objectAtIndex:currentIndex] objectForKey:@&quot;profil profondeur&quot;]] retain];<br />		<br />&nbsp; &nbsp; [self editFields];<br />&nbsp; &nbsp; [self updateUI];<br />}<br />


Ce n'est que lorsque je ferme mon document et que je l'ouvre à  nouveau que je peux accéder à  ce nouveau profil.  :why?:

Que se passe-t-il ?

Merci d'avance  :)

Réponses

  • Eddy58Eddy58 Membre
    15:48 modifié #2
    Oui j'ai déjà  eu affaire a ce problème très gênant. :crackboom:-
    C'est un array enregistré dans un fichier que j'utilisais dans deux classes.
    J'ai résolu le problème en ouvrant le fichier dans lequel est contenu l'array que quand j'en avais besoin pour faire des modifs dedans, ensuite une fois les modification faites, j'enregistrais l'array dans le fichier avant de le libérer. Et ceci dans les deux classes.
    Je ne sais pas si c'est possible dans ton cas de faire comme j'ai fait, car c'est un array dont je récuperais seulement les valeurs a l'initialisation, et que je modifiais quand nécessaire, alors que toi je pense tu t'en sers pas mal de fois dans ton soft. En suivant ma technique, peut-être peut-tu copier l'array chargé dans un autre array avant de le libérer afin d'éviter le conflit entre les deux classes ?
    Je pense qu'il existe d'autres techniques pour remédier à  ce problème, mais lesquelles ? ???
  • VeillardVeillard Membre
    15:48 modifié #3
    Non en effet je dois garder ouvert le fichier tant que la consultation n'est pas finie. Je vais essayer en copiant l'array...
  • VeillardVeillard Membre
    15:48 modifié #4
    J'ai essayé de faire une copie de tableau à  tableau => rien  :'( :'( :'( :'(

    Quelqu'un a-t-il une solution  ???

    Merci
  • mpergandmpergand Membre
    15:48 modifié #5
    Salut Favouille,

    Non j'ai pas la soluce car déjà  je ne comprends pas pourquoi tu fais une copie de ton tableau, pour ta classe profil.m, un pointeur sur ce tableau devrait suffire.
    Et justement vérifie que ce pointeur que tu initialises dans handlePlongeeClick, c'est bien le même que tu utilises dans profil.m.

    Sinon un banal reloadData ;)
  • VeillardVeillard Membre
    15:48 modifié #6
    Salut mpergand  :)

    Voilà , j'ai essayé plusieurs techniques comme celle d'Eddy58 qui m'a suggéré de copier un array dans un autre array.

    Sinon, ce que j'ai fait, c'est déclarer l'array dans les 2 classes :

    - dans "Carnet.h"
    #import &lt;Cocoa/Cocoa.h&gt;<br /><br />NSMutableArray	 *profilProfondeur;<br /><br />@interface Carnet : NSDocument<br />{......<br /><br />
    


    - puis dans "Profil.h"
    #import &lt;Cocoa/Cocoa.h&gt;<br /><br />extern NSMutableArray	*profilProfondeur;<br /><br />@interface Profil : NSView<br />{......<br />
    


    - puis dans "Carnet.m", je charge les données dans l'array :
    - (IBAction)handlePlongeeClick:(id)sender<br />{<br />&nbsp; &nbsp; currentIndex = [sender selectedRow];<br />		if (currentIndex == -1) return;<br />		<br />	profilProfondeur = [[[tableauDesPlongees objectAtIndex:currentIndex] objectForKey:@&quot;profil profondeur&quot;] retain];<br />		<br />	[self editFields];<br />	[self updateUI];<br />}<br />
    


    - enfin, j'utilise l'array pour tracer mon profil dans "Profil.m"

    Peut-être ai-je oublié quelquechose  ???
  • Eddy58Eddy58 Membre
    15:48 modifié #7
    Ha oui tu n'encapsules pas ton NSMutableArray... :-\
    Avec ce que propose mpergand, la solution est en effet de peut-être utiliser un seul et même pointeur, tu ouvres ton array dans Carnet.m, puis, en codant proprement ;) et en supprimant ta variable globale (tu vois je suis très partisant de l'encapsulation ;D), tu te fais une méthode accesseur dans carnet.m, et ensuite tu demandes à  l'accesseur le pointeur de ton array dans Profil.m... :)
  • VeillardVeillard Membre
    15:48 modifié #8
    Ca commence à  être un peu technique...

    Je suppose que je dois encapsuler l'array comme ceci dans "Carnet.m":
    - (void)setProfilProfondeur:(NSMutableArray *)profil<br />{<br />	if (profilProfondeur != profil)<br />	{<br />		[profilProfondeur release];<br />		profilProfondeur = [profil retain];<br />	}<br />}<br />
    


    Après j'avoue que je ne sais pas comment faire (le bouquin un un peu sec sur le sujet)  :P
  • mpergandmpergand Membre
    15:48 modifié #9
    C'est quoi c'est variable à  l'extérieur de NSDocument ???

    Si tu charges plusieurs documents, ils partageront la même variable profilProfondeur ???

    Il n'y a aucune raison d'utiliser ce genre de variables en prog objets, à  part pour définir des variables de classe ( en ObjC), ce qui n'est pas le cas ici.

    Donc tu va définir une variable d'instance pour ta classe profil.m avec un bel accesseur et dans handlePlongeeClick faire: currentProfil.setProfileData(profileArray);

    De plus ta classe profil est un NSView ??? ben :why?: tu dessines quelque chose de spécial dans cette vue ?

    En théorie toutes ces classes devraient être des classes contrôleurs, bon ça c'est pas le plus grave, car je crois qu'il y a un gros problème de structure/logique dans ton prog, :(

    Le plus simple serait de tout gérer dans Carnet ?

    le retain est inutile, je crois bien, tu fais un release où:
    profilProfondeur = [[[tableauDesPlongees objectAtIndex:currentIndex] objectForKey:@profil profondeur] retain];

    le tableau est déjà  retenu par le dictionary, il me semble.
  • VeillardVeillard Membre
    15:48 modifié #10
    C'est quoi c'est variable à  l'extérieur de NSDocument

    Je pensais qu'en mettant cette variable en global, on pouvait accéder à  son contenu à  partir des deux classes.

    De plus ta classe profil est un NSView  ben  tu dessines quelque chose de spécial dans cette vue ?

    Oui, je trace le profil dans la View.

    Je vais tenter les accesseurs
  • mpergandmpergand Membre
    15:48 modifié #11
    Grilled par Eddy ;D


    Je pensais qu'en mettant cette variable en global, on pouvait accéder à  son contenu à  partir des deux classes.


    Oui , mais global veut dire global au programme tout entier.

    Mais si c'est un NSView, c'est un setNeedsDisplay qu'il faut faire pour actualiser l'affichage...
  • VeillardVeillard Membre
    15:48 modifié #12
    Bon, j'ai mis mon array en local. Du coup il n'est plus reconnu dans Profil.m (logique...)
    J'ai voulu séparer "Profil.m" pour deux  raisons :
    - la première c'est que "Carnet.m" comporte plus de 1500 lignes  ;D
    - la seconde parce que c'est une NSView.

    J'ai essayé les accesseurs  :'( :'( :'( sans commentaires je bidouille sans y comprendre grand chose ou si peu  :P

    Ce que j'ai fait :

    - dans "Carnet.m", j'ai écrit :
    - (NSMutableArray *)profilProfondeur;
    {
    profilProfondeur = [[tableauDesPlongees objectAtIndex:currentIndex] objectForKey:@profil profondeur];

    return profilProfondeur;
    }

    - (void)setProfilProfondeur:(NSMutableArray *)depthProfile
    {
    [depthProfile retain];
    [profilProfondeur release];
    profilProfondeur = depthProfile;
    }


    Puis quid des instructions à  écrire dans "Profil.m" pour récupérer mes données ???
  • Eddy58Eddy58 Membre
    15:48 modifié #13
    Déjà , dans Carnet.m, modifie ta méthode accesseur de type get en :
    <br />- (NSMutableArray *)profilProfondeur;<br />{<br />   return profilProfondeur;<br />}<br />
    


    Ensuite, toujours dans Carnet.m, tu initialises ton array comme tu veux, ensuite dès que tu as fait l'initialisation de ton array, tu fais :
    <br />[self setProfileProfondeur:profilProfondeur];<br />
    


    Voilà  pour carnet.m. Ensuite, pour ta classe Profile, il te faut tout d'abord informer ta classe pour qu'elle puisse accéder à  l'accesseur. Dans Profile.h, rajoute ceci en début de listing après les directives #import :
    <br />@class Carnet;<br />
    

    Puis dans Profile.m, tu rajoutes un import :
    <br />#import &quot;Carnet.h&quot;<br />
    


    Et puis enfin, pour récupérer ton array, tu utilises l'instruction suivante, à  mettre ou tu le sens tout dépend le fonctionnement :
    <br />NSMutableArray *profilProfondeur=[Carnet profilProfondeur];<br />
    


    Et puis effectivement, comme le dis mpergand, tu as une sous-classe de NSView, donc quand tu as terminé tes opérations de tracé, il faut rafraà®chir ta view :
    <br />[self setNeedsDisplay];<br />
    


    Voilà  espérons que ca marche. :)
  • mpergandmpergand Membre
    15:48 modifié #14
    ??? :o

    C'est dans profil.m qu'i faut déclarer profilPronfondeur, pas dans carnet.m

    donc tu déclares une variable d'instance dans profil.h:

    NSArray* profil;

    et tu implémentes dans profil.m, la methode:

    -(void) setProfilData:(NSArray*) prof
    {
    profil=prof;
    }

    Donc dans carnet.m tu as besoin d'un outlet sur la vue profil et dans handleClick tu fais:

    NSArray* profilProfondeur = [[tableauDesPlongees objectAtIndex:currentIndex] objectForKey:@profil profondeur];
    [profilView setProfilData: profilPronfondeur];

    [profilView setNeedsDisplay:YES];
  • VeillardVeillard Membre
    15:48 modifié #15
    Merci à  tous pour votre aide, ça fait 2 jours que je galère !  :P :P :P

    Je vous tiens au courant...
  • Eddy58Eddy58 Membre
    15:48 modifié #16
    dans 1100972815:

    ??? :o

    C'est dans profil.m qu'i faut déclarer profilPronfondeur, pas dans carnet.m


    Oui tout dépend comment on voit les choses, effectivement côté fonctionnement je n'ai pas pensé pareil mpergand. Ta méthode a l'air plus propre je pense. :)
  • mpergandmpergand Membre
    novembre 2004 modifié #17
    encore grilled >:(

    Favouille, tu as encore quelques progrès à  faire en programmation objets ;)

    Eddy:


    Puis dans Profile.m, tu rajoutes un import :
    Code:
    #import "Carnet.h"


    profile.m n'a besoin de connaà®tre Carnet.m


    Et puis enfin, pour récupérer ton array, tu utilises l'instruction suivante, à  mettre ou tu le sens tout dépend le fonctionnement :
    Code:
    NSMutableArray *profilProfondeur=[Carnet profilProfondeur];

    :o

    c'est pas très objet ça, un peu bricolo j'dirais ;D

    [edit]


    Oui tout dépend comment on voit les choses, effectivement côté fonctionnement je n'ai pas pensé pareil mpergand. Ta méthode a l'air plus propre je pense.                                                                 


    no comment  ;)

  • Eddy58Eddy58 Membre
    15:48 modifié #18
    dans 1100974614:

    c'est pas très objet ça, un peu bricolo j'dirais ;D

    Oui tout à  fait, c'est pourquoi je trouve ta méthode plus clean. :)
  • VeillardVeillard Membre
    15:48 modifié #19
    Bon, après quelques essais voici le verdict...  :'( :'( :'(


    C'est dans profil.m qu'i faut déclarer profilPronfondeur, pas dans carnet.m

    Pour répondre à  mpergand, j'ai déclaré l'arré dans Carnet parce que je l'utilise plusieurs fois dans d'autres situations (ex : ajout de l'array dans un dictionary...) de plus, à  la compilation il ne me met 9 erreurs : "profilProfondeur undeclared"  :-\

    Avec la méthode d'Eddy, j'ai :
    `Carnet&#39; may not respond to `+profilProfondeur&#39;<br />cannot find method `+profilProfondeur&#39;; return type `id&#39; assumed
    


    Que fais-je sachant que l'array est plusieurs fois utilisé dans Carnet...







  • Eddy58Eddy58 Membre
    15:48 modifié #20
    Et la méthode de mpergand marche pas ? ???

    Sinon, le cas échéant, tu peux utiliser une notification pour transmettre ton pointeur. J'utilise souvent cette méthode, elle marche à  coup sûr, et elle n'est pas lourde à  mettre en oeuvre....
  • VeillardVeillard Membre
    15:48 modifié #21
    Favouille, tu as encore quelques progrès à  faire en programmation objets

    Je rectifie : beaucoup de progrès  ;D

    La preuve : à  la compilation je bloque sur "profilView" de :
    [profilView setProfilData: profilPronfondeur];
    


    Je ne sais pas à  quoi ça correspond...

    Et la méthode de mpergand marche pas ?

    Je suis à  fond dessus...
  • mpergandmpergand Membre
    15:48 modifié #22
    dans 1100976014:

    j'ai déclaré l'arré dans Carnet parce que je l'utilise plusieurs fois dans d'autres situations



    Bon, c'est pas un problème, tu as donc une variable d'instance dans carnet.m qui contient le tableau des données du profil courrant, donc tu fait:
    <br />NSMutableArray* profilProfondeur;   // variable declarée dans carnet.h<br /><br />......<br /><br />/* handleClick  */<br />profilProfondeur = [[tableauDesPlongees objectAtIndex:currentIndex] objectForKey:@&quot;profil profondeur&quot;];<br />[profilView setProfilData: profilPronfondeur];<br /><br />[profilView setNeedsDisplay:YES];
    


    L'important est que profilView sache avec quelles données travailler
  • VeillardVeillard Membre
    15:48 modifié #23
    On y est presque (j'espère)  :P
    Reste que j'ai une erreur de compil avec "profilView" qui est "undeclared"
  • mpergandmpergand Membre
    novembre 2004 modifié #24
    Ben la vue que ta subclassée dans IB pour afficher le profil elle s'appelle comment :P

    [edit]

    ha oui tu l'as appelée Profil !!
  • VeillardVeillard Membre
    15:48 modifié #25
    Oui en effet je m'en suis rendu compte quand j'ai fait une pause  :P
    Dans carnet.h j'ai déclaré : "NSView *profilView", puis dans IB j'ai fait le lien entre "profilView" et la zone de tracage. Je pense que c'est ça qu'il fallait faire  :-\

    J'ai compilé et ça marche ! :brule: :brule: :brule:

    Par contre, l'ancien profil n'est pas effacé, tout se superpose petit à  petit...
  • VeillardVeillard Membre
    15:48 modifié #26
    J'avais oublié ceci...

    <br />warning: `NSView&#39; may not respond to `-setProfilData:&#39;<br />warning: cannot find method `-setProfilData:&#39;; return type `id&#39; assumed<br />
    


    ???
  • mpergandmpergand Membre
    15:48 modifié #27
    Profil* profilView;

    ça devrait aller mieux !
  • VeillardVeillard Membre
    15:48 modifié #28
    Ca ne change rien...
  • mpergandmpergand Membre
    15:48 modifié #29
    Tu as toujours les warnings ???

    Pour le problème de redessin, je pige pas bien non plus  :D
  • VeillardVeillard Membre
    15:48 modifié #30
    Tu as toujours les warnings


    Oui

    En ce qui concerne les dessins, à  chaque fois que je clique sur une plongée, le profil correspondant est correstement tracé mis à  part que le ou les précédents profils ne sont pas effacés...
  • VeillardVeillard Membre
    15:48 modifié #31
    Ca y est, je n'ai plus les warnings  :crackboom:- Il suffisait de rajouter profil.h en en-tête pour la déclaration des prototypes...

    Par contre, en ce qui concerne les graphiques, je vais voir si il n'y a pas une fonction pour effacer la View à  chaque nouvel appel.

    En tout cas merci beaucoup pour ton aide précieuse sans oublier Eddy.  :trinque: :trinque: :trinque:
Connectez-vous ou Inscrivez-vous pour répondre.