[resolu] @public ?

tabliertablier Membre
avril 2008 modifié dans API AppKit #1
J'ai beau lire et relire la doc, je ne trouve pas! (et je ne trouve pas non plus d'exemple là -dessus)
J'ai 3 objets 'fils' de NSObject. Dans un des objets, je déclare:
@interface Controleur : NSObject {<br />...... ici les déclarations protégées.<br />@public<br /> BOOL&nbsp; bool1, bool2, ........bool27 ;<br /> int&nbsp; int1, int2, ........ int5 ;<br /> NSMutableString *mut1, *mut2, ...... *mut7 ;<br />}<br />.... ici les méthodes<br />@end

D'après la doc, les champs déclarés @public sont visibles dans tout le programme. Tous mes champs déclarés @public  doivent être utilisés par +sieurs méthodes de 2 autres objets. Ces objets sont batis sur le même modèle que le controleur:
@interface objet1_ou_2 : NSObject {<br />...... ici les déclarations<br />}<br />.... ici les méthodes<br />@end
Je n'arrive pas à  acceder à  mes variables @public depuis les méthodes des 2 objets. J'ai essayé extern et également d'ajouter un import du controleur.h dans les .h des deux objets. ça ne marche pas: j'ai soit l'erreur "première définition d'une variable", soit un plantage au lancement!

Comment dois-je m'y prendre pour rendre visibles dans d'autres objets des variables déclarées @public.
merci d'avance.

Réponses

  • schlumschlum Membre
    15:53 modifié #2
    Ben si ton instance de Controleur s'appelle "c", il faut faire c.bool1, ... , c.mut7, non ?  ???
  • Philippe49Philippe49 Membre
    15:53 modifié #3
    Pour moi, @public@private et @protected définissent des permissions d'accès, pas l'accès proprement dit.
    extern ne marche pas ?
  • Philippe49Philippe49 Membre
    15:53 modifié #4
    essai :
    Comme cela ça marche, mais bon, c'est le recours à  C

    ========================
    // fichier classA
    NSRect aFrame;

    @interface
    ...
    @end

    ====================
    //fichier classB
    extern NSRect aFrame;

    @implementation
    -(void)awakeFromNib{
    NSLog(@%f,aFrame.origin.x);
    ...
    }
  • tabliertablier Membre
    15:53 modifié #5
    Oui, pour moi aussi, @public definit l'autorisation d'accès, et c'est tout.

    J'ai oublié de dire que les trois objets sont définis sous IBuilder. ils sont accessibles par des IBOutlets. J'ai ajouter un outlet à  un des 2 objets, et j'ai relié l'objet au controleur, tel que [cetOutlet methodeDuControleur] ; fonctionne correctement dans l'objet. Donc cetOutlet pointe bien l'instance de controleur. Néanmoins, cetOutlet->bool1 me donne l'erreur:
    error: 'struct objc_object' has no member named 'pC_dosSrc'
    et cetOutlet.bool1 me donne l'erreur:
    error: request for member 'pC_dosSrc' in something not a structure or union

    Il y a vraiment quelque chose que je ne comprends pas!!

    Je n'ai rien contre l'emploi du C! Néanmoins, j'aimerais bien savoir comment on s'y prend avec @public
    (la curiosité est un vilain défaut, sauf pour les scientifiques!)
  • Philippe49Philippe49 Membre
    avril 2008 modifié #6
    On peut définir des variables globales dans le fichier monAppli_Prefix.pch


    //
    // Prefix header for all source files of the 'ClosingBox' target in the 'ClosingBox' project
    //

    #ifdef __OBJC__
       #import <Cocoa/Cocoa.h>
    #endif


    NSString * aString;


    ========================
    // fichier ClassA

    @implementation ClassA
    -(void) mouseDown:(NSEvent *) theEvent {
        [aString release];
        aString=@deuxieme version ;
    }
    @end

    ====================
    //fichier classB


    @implementation ClassB
    -(void)awakeFromNib{
       aString=@premier version;
    }
  • Philippe49Philippe49 Membre
    avril 2008 modifié #7
    dans 1209387832:

    et cetOutlet.bool1 me donne l'erreur:


    Il faudrait que bool1 soit défini comme une property.

    Autre solution, utiliser KVC : [cetOutlet valueForKey:@bool1] qui devrait renvoyer un NSNumber.

    dans 1209387832:
    j'aimerais bien savoir comment on s'y prend avec @public
    (la curiosité est un vilain défaut, sauf pour les scientifiques!)

    Quand à  @public et ses associés, je suis comme toi, je suis curieux de savoir dans quelle occasion, cela sert. Cela me semble être là  pour "faire propre" dans des classes à  utilisation sécurisée.
  • schlumschlum Membre
    avril 2008 modifié #8
    Oui, désolé, flèche pas point (je suis dans le C++ là , c'est pour ça  :P)

    Ce code fonctionne chez moi sans problèmes...
    #import &lt;Foundation/Foundation.h&gt;<br /><br />@interface Test : NSObject<br />{<br />	@public<br />	int myTest;<br />}<br />@end<br /><br />@implementation Test<br /><br />@end<br /><br />int main (int argc, const char * argv&#91;]) {<br />	Test *t = [[Test alloc] init];<br />	t-&gt;myTest = 5;<br />	NSLog(@&quot;%d&quot;,t-&gt;myTest);<br />	[t release];<br />	return 0;<br />}
    

  • Philippe49Philippe49 Membre
    15:53 modifié #9
    Je confirme l'essai de Schlum avec des fichiers à  compilation séparée.
  • tabliertablier Membre
    15:53 modifié #10
    Oui, ça marche. Mais mes objets sont instanciés automatiquements au lancement, car ils ont été générés sous interface Builder.
    Bon, j'ai une solution:  Comme dit précédemment, j'ai dans l'objet un outlet qui pointe le controleur et j'ai essayer: cetOutlet->bool1, ce qui me donne une errreur (voir plus haut).
    Vu le code de schlum, j'ai modifié mon code ainsi:
    #import &quot;controleur.h&quot;<br /><br />@implementation&nbsp; objet_1<br />- (void)la_methode<br />{<br />Controleur&nbsp; *truc;<br />BOOL&nbsp; boule ;<br /><br />&nbsp; &nbsp; truc = cetOutlet;<br />&nbsp; &nbsp; boule = truc-&gt;bool1 ;<br /> ..... etc
    
    ça marche! Donc mon erreur a été de croire que le compilateur savait sur quoi pointait cetOutlet!
    Pour vérification j'ai écrit: boule = ((Controleur *)cetOutlet)->bool1 ; ça marche aussi!

    Merci pour votre aide.

  • schlumschlum Membre
    15:53 modifié #11
    Je ne comprends pas... Quand on définit un outlet, en général on met le vrai type derrière non ?  ???

    IBOutlet Controleur *cetOutlet;

    IBOutlet n'est pas un type, c'est juste un marqueur pour IB !
  • tabliertablier Membre
    15:53 modifié #12
    Tout à  fait d'accord, mais IB met par défaut id. Pour le type des objets graphiques de l'interface le menu déroulant est suffisant, mais pour les autres objets, en général je laisse id.  C'est la première fois que cela me pose un problème en 4 ans. Néanmoins je retiens la leçon.
    Sous Xcode 3 IB incite à  mettre le type d'objet pointé, mais sous 2.5 ce n'est pas évident.
    Bon je vais retourner dans IB et mettre le bon type d'objet pour cet outlet.
  • psychoh13psychoh13 Mothership Developer Membre
    15:53 modifié #13
    Pour commencer, la seule chose que définit "id" c'est un pointeur sur une structure contenant un champ "Class", donc du point de vu du C, il n'y a que ça dedans, et donc l'écriture en C pur monObjet->var est un accès direct à  un champ dans un pointeur sur structure. à‰tant donné que seul isa est défini dans cette structure le compilateur n'est pas capable de trouver les autres variables. Il faut donc utiliser un typage statique.
    De même pour les propriétés Objective-C 2 qui s'écrivent monObjet.var.

    En ce qui concerne le @public, en programmation orientée-objet, c'est sale. Et ça n'est utilisé que dans des cas très particulier. Personnellement, je ne l'ai jamais utilisé, par contre je l'ai déjà  vu utilisé dans les sources de GNUStep, mais uniquement dans des classes privées, dans des classes qui utilisent généralement d'autres classes et qui rend l'accès plus rapide.
  • schlumschlum Membre
    15:53 modifié #14
    C'est pas forcément sale, quand on veut créer des structures " intelligentes ".
    Mais en Obj-C ça n'a pas grand sens puisqu'on ne peut pas instancier sur la pile...
    Jamais utilisé non plus.
  • psychoh13psychoh13 Mothership Developer Membre
    15:53 modifié #15
    Voilà  ta "structure intelligente", un magnifique hack très crade :
    #import &lt;Foundation/Foundation.h&gt;<br /><br />typedef struct Intell {<br />&nbsp; &nbsp; Class isa;<br />&nbsp; &nbsp; unsigned var;<br />} Intell;<br /><br />@interface Test : NSObject<br />- (void)print;<br />@end<br />@implementation Test<br />- (void)print<br />{<br />&nbsp; &nbsp; printf(&quot;%u&quot;, ((Intell*)self)-&gt;var);<br />}<br />@end<br /><br />int main (int argc, const char * argv&#91;]) {<br />&nbsp; &nbsp; NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; Intell obj = {[Test class], 5};<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; [(id)&amp;obj print];<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; [pool drain];<br />&nbsp; &nbsp; return 0;<br />}
    

    :P :P :o
  • schlumschlum Membre
    15:53 modifié #16
    Non seulement c'est crade, mais là  pour le coup, la notion de constructeur/destructeur devient très floue  :P

    L'intérêt d'un smart pointer, c'est de pourvoir allouer des trucs dans le constructeur et que ça soit désalloué dans le destructeur automatiquement (donc en cas d'exception levée etc...)
Connectez-vous ou Inscrivez-vous pour répondre.