Reconnaà®tre une variable d'une classe à  l'autre

muqaddarmuqaddar Administrateur
09:20 modifié dans API AppKit #1
Salut,

Voilà , j'ai 2 classes controlleurs dont l'une doit se servir d'un array déclaré et rempli dans la première. Ce premier controlleur dispose de méthodes accesseurs sur cette variables d'instance array.
Dans le deuxième controlleur qui se sert de l'array du premier, j'importe le .h du premier controlleur. Je pensais que les accesseurs permettaient de facilement faire reconnaà®tre cette variable d'instance, mais pour le second controlleur, elle n'est pas déclarée, malgré l'importation du .h.
Du coup, je suis obligé d'ajouter un outlet qui pointe vers le premier controlleurs et de lui envoyer une méthode -(id)getArray pour qu'il me retourne l'array du premier controlleur. ça marche, mais je trouve pas ça glops.  :-\
N'y a t-il aucun moyen d'importer l'array pour qu'il soit reconnu comme déclaré et rempli ds le deuxième controlleur, sans avoir à  ajouter une méthode ?

Réponses

  • ClicCoolClicCool Membre
    09:20 modifié #2
    Salut Oxitan :)

    L'importation du header de ton controleur1 permet à  ton controleur2 d'en connaitre la nature.
    Ce qui te permet:
    - de déclarer un outlet de type Controleur1*
    - d'adresseur à  l'instance de Controleur1 pointé par ton outlet les méthodes d'instances (-) dont les fameux accesseurs
    -d'adresser à  la Classe Controleur1 des méthodes de classes (+) éventuellement définies.

    Y'a aucune raison pour que l'importation du header apporte autre chose que les infos du header...
    Donc ton controller2 connait l'existence des variables d'instances et de leurs accesseurs, mais ne peux connaitre la valeur de ces variables pour chaque instance sans recourir à  un outlet pointant sur l'instance et aux accesseurs appliqués à  cette instance !.

    Si ta classe Controleur1 doit être un singleton (unique instance) tu peux peut-être implémenter une méthode de classe renvoyant l'unique instance pour y adresser les méthodes accesseurs, voire même une méthode de classe renvoyant directement les valeurs voulues. Là  t'as plus besoin d'outlet, tu causes directement avec la classe.
    ex pour la première méthode:
    monControleur1* = [Controleur1 sharedInstance];<br />NSArray* monTAbleau = [monControleur1 getDataArray];
    

    pour la deuxième méthode:
    NSArray* monTAbleau = [Controleur1 getSharedArray];
    


    Sinon peut-être devrais tu revoir la structure de tes contrôleurs si tu veux éviter qu'ils dépendent l'un de l'autre et éviter les outlets ... ?
  • ClicCoolClicCool Membre
    09:20 modifié #3
    Pour l'implémentation d'une Classe avec une instance unique partagée jettes un oeil là  dessus:

    Creating a Singleton Instance

    Cette stratégie n'est pas souvent appliquée à  de bêtes controller mais elle est très utile ++ ;)
  • mpergandmpergand Membre
    novembre 2004 modifié #4
    Salut à  tous,

    Résumons la situation:
    Nous avons un contrôleur principal, mais c'est un gros fainéant, il délègue plein de boulot à  son contrôleur auxiliaire, et comme il sait où il crèche il lui refile directement le taff, il n'attend pas que son subalterne de contrôleur lui demande. :D

    Conclusion:
    Le contrôleur principal possède un outlet sur le contrôleur auxiliaire et lui communique les données avec lesquelles travailler ( par accesseurs ou non)
  • muqaddarmuqaddar Administrateur
    09:20 modifié #5
    Bienvenue chez les cacaoculteurs mpergand... ;)
    Oui, pour l'instant, c'est exactement ce que j'ai fait. Outlet + méthode.

    ClicCool, je vais regarder cette histoire de singleton... mais ça a l'air chaud.
  • mpergandmpergand Membre
    novembre 2004 modifié #6

    Oui, pour l'instant, c'est exactement ce que j'ai fait. Outlet + méthode.


    Oui mais tu semble procéder à  l'envers, si j'ai bien compris. Le contrôleur auxiliaire n'a pas besion de connaà®tre le contrôleur principal et ne devrait avoir accès qu'aux données le concernant.

    ClicCool, je vais regarder cette histoire de singleton... mais ça a l'air chaud.


    Déclare ton NSArray static, si u veux une variable de classe, mais si ton contrôleur fait partie d'un NSDocument, c'est râpé.



    Bienvenue chez les cacaoculteurs mpergand..


    Ouais ! et dans trois ans j'suis à  mon compte ;D
  • muqaddarmuqaddar Administrateur
    09:20 modifié #7
    C'est le controlleur principal qui fait des getArray sur les varaibles d'instances des controlleurs auxilliaires, pour répondre à  ta question. ;)
  • muqaddarmuqaddar Administrateur
    09:20 modifié #8
    Ah je sèche.

    Ceci me renvoie des NULL.

    NSMutableArray* loadArray = [appController getArray];
    NSLog(@loadArray : %@", loadArray);

    Quand j'essaie d'importer le contenu d'un tableau ds mon controlleur principal...
    L'outlet est bien connecté pourtant au controlleur secondaire...
  • ClicCoolClicCool Membre
    09:20 modifié #9
    Salut Oxitan :)

    Comment t'as implémenté ton getArray ?
    Qu'est-ce qui est Null ? L'array renvoyé ou son contenu ?

    P.S.: Sans indiscrétions, pourquoi ton contrôleur principal a-t-il besoin de récupérer un array du contrôleur seçondaire en fait ?
    Si c'est pour servir de data source, il vaudrait mieux directement définir le controleur seçondaire comme data source non ?
  • muqaddarmuqaddar Administrateur
    09:20 modifié #10
    Quand je fais un NSLog de l'array : NULL.

    Oui, c'est pour servir de datasource... je vais essayer comme tu dis.
    merci.
  • muqaddarmuqaddar Administrateur
    09:20 modifié #11
    dans 1101819277:

    Si c'est pour servir de data source, il vaudrait mieux directement définir le controleur seçondaire comme data source non ?


    En fait, là , je ne vois pas comment faire dans IB... :( ???
  • ClicCoolClicCool Membre
    09:20 modifié #12
    dans 1101821444:

    dans 1101819277:

    Si c'est pour servir de data source, il vaudrait mieux directement définir le controleur seçondaire comme data source non ?


    En fait, là , je ne vois pas comment faire dans IB... :( ???


    Ben comme avec un controleur habituel en connectant la TableView avec le controleurSecondaire, choisissant l'outlet "datasource" et en cliquant sur connecter....

    Ton controleur seçondaire n'est pas instancié dans IB ?

    Sinon tu peux envoyer à  la NSTableView un setDataSource:monControleurSecondaire.
  • muqaddarmuqaddar Administrateur
    novembre 2004 modifié #13
    Mais j'ai pas de tableView !!! Je veux juste récupérer le contenu d'un array ;)

    Sinon, en passant par un outlet, ça marche ds le awakeFromNib, il choppe bien le tableau mais dans le init ça marche pas, et je ne vois pas pourquoi ?
    Il y a un ordre de chargement des controlleurs ???
  • ClicCoolClicCool Membre
    09:20 modifié #14
    ouhla ouhla ...

    tu me dis que l' controleur seçondaire sert de data source ... de data source de quoi en fait ? ???

    Cet Array contien des éléments en provenance du model objet. Right ?
    Puis gérées, filtrées, triées, modifiées par le contrôleur Seçondaire. Right ?

    Puis untilisées par le controleur Principal. Right ?
    Qu'en fait le controleur principal ? C'est lui qui gère l'affichage ? ou en a-t-il besoin pour gérer des filtrages et/ou synchro ?

    Je suis quelques peu dans le brouillard avec ton pb :(



    [size=6pt]PS: J'aurais jamais du accepter de trinquer au pot de départ de ma secrétaire avec du punch ...[/size]  :P
  • muqaddarmuqaddar Administrateur
    09:20 modifié #15
    Le controlleur principal doit simplement se contenter de récupérer des données d'un array, géré dans un controlleur secondaire, c'est tout. :)

    D'où mon [outlet getArrayDuCtrlSec] dans le controlleur principal.
    Si j'affiche ce que je récupère  juste en dessous de mon getArray, no soucy (mon nouveau tab est uen var d'instance). Mais si je l'affiche ds uen autre méthode de mon ctrl principal, array me renvoie (null), malgré la var d'instance...
  • ClicCoolClicCool Membre
    09:20 modifié #16
    dans 1101823119:

    Si j'affiche ce que je récupère  juste en dessous de mon getArray, no soucy (mon nouveau tab est uen var d'instance). Mais si je l'affiche ds uen autre méthode de mon ctrl principal, array me renvoie (null), malgré la var d'instance...


    Ahaaaaaaaaaaaaaa !

    Donc en fait ru récupères bien un Array valide que tu stocke dans une variable d'instance. Et c'est après que les choses se gatent quand tu cherches à  utiliser l'array pointé par ta variable d'instance ?

    Alors là  c'est clair, il te manque un retain sur ta variable d'instance !

    P.S. Qu'est-ce qu'il en fait ton controleur principal de l'array ?
  • muqaddarmuqaddar Administrateur
    09:20 modifié #17
    Mon controlleur principal lit les données de l'array et en aucun cas ne les modifie.

    Même avec un retain, mon array importé n'est pas reconnu ds les autres méthodes.

    loadArray = [NSMutableArray alloc] initWithArray:[appelControllerOutlet getArray retain];
  • ClicCoolClicCool Membre
    novembre 2004 modifié #18
    dans 1101832963:


    Un alloc init doublé d'un retain ! t'y as pas été de main morte sur ce coup ;)
    ça fait un retain de trop à  priori.

    Pourtant je ne vois pas comment un Array valide juste après sa réception peut devenir invalide par la suite. ???
    Ne modifies tu pas tout simplement la valeur de ta variable quelque part dans ton code ?
    Si tu écris loadArray = nil; , même si ton array reste retenu, tu en perds toute trace et plantage et fuite mémoire assurée.

    Sinon es tu bien sur de ne pas faire de release sur cette variable ? (au moins 2 fois puisque le retain count de ton array est au moins égal à  2 après Alloc - init + retain ;) )
  • muqaddarmuqaddar Administrateur
    09:20 modifié #19
    Je ne la release pas.
    En fait, j'ai remarqué 2 choses :

    1- pour que l'array soit importé, je dois créer ma variable d'instance dasn le awakeFromNib et non ds le init, là  tout se suite après, je peux afficher mon array

    2- ma variable d'instance est bien lue dans certaines méthodes, mais pas dans toutes où elle renvoie alors (null) ds le nslog

    Bref, je ne comprends plus rien.

    La méthode en question est celle-ci

    <br />- (NSString*)getNameWithId: (NSNumber* )appId<br />{<br />	NSLog(@&quot;loadedArray: %@&quot;, loadedArray);<br />}<br />
    


    loaded array étant le tableau importé.
  • muqaddarmuqaddar Administrateur
    09:20 modifié #20
    Bon, je crois compendre ce qui se passe.

    Mon array n'arrive pas à  s'importer quand je lance le programme, comme si il n'était pas encore créé ou rempli par son propre controlleur.

    Parce que chaque fois que je l'importe dans une méthode IBAction ou autre , donc que le programme est déjà  lancé, là  il le voit. Vous me suivez ?
  • muqaddarmuqaddar Administrateur
    09:20 modifié #21
    Bon, bein ça marche maintenant... Et me demandez pas pourquoi.

    J'ai juste appelé la méthode qui importe le tableau par une autre méthode et là , le tableau importé est reconnu...
  • mpergandmpergand Membre
    décembre 2004 modifié #22
    Vous me suivez ?


    Non ! ;D


    Sinon, en passant par un outlet, ça marche ds le awakeFromNib, il choppe bien le tableau mais dans le init ça marche pas, et je ne vois pas pourquoi ?

    On peut effectuer l'initialisation à  deux endroits:

    - dans init, limité aux variables ne faisant pas référence à  d'autres objets du nib, ceux-ci étant dans un état indéterminé.

    - dans awakeFromNib, l'appkit garanti, lorsque cette méthode est appelée, que tous les objets du nib ont été instanciés et initialisés.
  • muqaddarmuqaddar Administrateur
    09:20 modifié #23
    Merci pour ces précisions mpergand. ;)
    Il faudra que j'essaie de comprendre pourquoi ça marche maintenant.
Connectez-vous ou Inscrivez-vous pour répondre.