IBoutlets 0x0

neurosupherotneurosupherot Membre
11:37 modifié dans API AppKit #1
Bonjour :)

J'ai commencé cocoa il y quelques jours maintenant, j'ai toujours réussi à  me débrouiller avec google mais j'avoue que là  ça se corse un peu.

en gros j'ai un controlleur nsobject nommé recieverController avec un "IBOutlet nswindow* wnd".

j'ai lié le tout avec une fenêtre dans interface builder

le problème est que lorque j'instancie mon controlleur (r = [recieverController alloc])

son attribut wnd vaut 0x0. il n'existe pas, comme s'il n'était pas lié.

est-ce qu'il est alors impossible d'instancier des IBOutlets?

Pouvez-vous m'éclairer? merci

Réponses

  • NseaProtectorNseaProtector Membre
    11:37 modifié #2
    T'as question me parait pas super claire, un bout de code aurait aidé.
    Cependant comme il s'agit d'un objet ne faut-il pas faire un "init" ?
  • CéroceCéroce Membre, Modérateur
    11:37 modifié #3
    Bon, là  il va te falloir un petit plus que Google, à  commencer par une bonne doc: http://www.amazon.fr/Cocoa-par-pratique-Aaron-Hillegass/dp/2212112327/ref=sr_1_2?ie=UTF8&s=books&qid=1220607547&sr=8-2

    Mais pour répondre à  ta question: on n'instancie pas des IBOutlets. Les objets sont instanciés quand le nib est ouvert. Glisse un NSObject depuis la palette Library dans le nib et change sa classe dans l'inspecteur Class Identity pour qu'il corresponde à  la classe de ton contrôleur. Lance ton appli, et magique, l'outlet pointe sur le bon objet.

    Recherche le classique Currency Converter sur le site de Peupeul, et la lumière tu verras.
  • NoNo Membre
    septembre 2008 modifié #4
    dans 1220632349:

    Bonjour :)

    J'ai commencé cocoa il y quelques jours maintenant, j'ai toujours réussi à  me débrouiller avec google mais j'avoue que là  ça se corse un peu.

    en gros j'ai un controlleur nsobject nommé recieverController avec un "IBOutlet nswindow* wnd".

    j'ai lié le tout avec une fenêtre dans interface builder

    le problème est que lorque j'instancie mon controlleur (r = [recieverController alloc])

    son attribut wnd vaut 0x0. il n'existe pas, comme s'il n'était pas lié.

    est-ce qu'il est alors impossible d'instancier des IBOutlets?

    Pouvez-vous m'éclairer? merci


    Si tu as relié ton contrôleur à  ta fenêtre dans IB, c'est que ton objet contrôleur est instancié par IB.
    Il existe déjà , et tu n'as pas à  faire de alloc/init (car dans ce cas, tu créés un nouvel objet contrôleur complètement vide, d'où ton outlet valant 0).

    Tu peux faire exécuter du code d'initialisation à  ton objet contrôleur IB en ajoutant la méthode awakeFromNib (- (void)awakeFromNib) dans le fichier .m d'implémentation.

    Edit: Grillé par Ceroce (chacun son tour).
  • neurosupherotneurosupherot Membre
    11:37 modifié #5
    Alors premièrement, merci beaucoup d'avoir répondu aussi vite! jamais j'ai vu sur des forums ( français en plus ) les gens répondre aussi vite donc merci à  tous :)

    ensuite, je vais essayer d'être plus clair.

    Le 0x0 est l'adresse de la variable de ma fenêtre lorsque je débugge.

    code de la classe appelante :

    <br />	recieverController* rc=[[recieverController alloc] initWithMessage:msg andIP:mIP];<br />	[rc appear:msg];<br />
    


    classe recieverController ( .h ) :

    <br />@class xmessage;<br /><br />@interface recieverController : NSObject {<br />	IBOutlet NSWindow *wnd;<br />	xmessage* mMsg;<br />	NSString* mIP;<br />}<br />-(void)appear:(xmessage*)msgr;<br />-(id)initWithMessage:(xmessage*)msgr andIP:(NSString*)ip;<br />@end<br />
    


    classe recieverController ( .m ) :

    <br />#import &quot;recieverController.h&quot;<br />#import &quot;xmessage.h&quot;<br /><br />@implementation recieverController<br /><br />- (id)initWithMessage:(xmessage*)msg&nbsp; andIP:(NSString*)ip<br />{<br />	if( ![super init] )<br />		return nil;<br />	mMsg=msg;<br />	mIP=ip;<br /><br />	return self;<br />}<br /><br />-(void)appear:(xmessage*)msgr<br />{<br />	NSString* content;<br />	content=[msgr getContent];<br />	[wnd orderFront:nil];// c&#39;est ici que ça vaut 0x0...<br />}<br /><br />- (void)dealloc<br />{<br />	[super dealloc];<br />}<br /><br />- (void)windowWillClose:(NSNotification*)inNotification<br />{<br />	[self autorelease];<br />}<br /><br />@end<br />
    


    voilà  les lignes de code les plus essentielles.

    J'avais testé le truc avec un IBOutlet lié à  un controlleur non instancié par le code mais par le IB et ça marchait.
    Je veux dire par là  que je n'ai pas fait de c = [[controlleur alloc] init];
    Le controlleur que j'avais testé était le controlleur délégue de NSApplication ( il était instancié tout seul au démarrage ) et là , la variable wnd valait qqch...

    j'espère avoir été un peu plus clair.
    merci encore de votre aide!
  • NoNo Membre
    11:37 modifié #6
    dans 1220634298:

    code de la classe appelante :
    <br />	recieverController* rc=[[recieverController alloc] initWithMessage:msg andIP:mIP];<br />	[rc appear:msg];<br />
    


    Je répète : là  est ton problème.

    Tu instancies un nouveau recieverController rc. Donc cx'est un nouvel objet vierge, avec tous ses outlets vides.
    Donc la méthode appear: essaie de faire afficher une fenêtre dont l'adresse (l'outlet) est nil.

    Pour t'aiguiller, une question : qu'elle est cette classe appelante ? et comment instancies tu un objet de cette classe appelante après démarrage de ton appli ?
  • neurosupherotneurosupherot Membre
    11:37 modifié #7
    Ok, je vais partir du début.
    j'ai la classe app qui est un NSObject et qui délègue File's Owner
    la classe app contient une variable srcctrl* scont;

    dans la classe app, scont = [srcctrl alloc]; est effectué dans le awakeFromNib.

    srcctrl a un NSArray,

    srcctrl instancie lors d'en évènement des clients et les stocke dans un NSArray.

    methode d'un nouveau client dans srcctrl.m:
    <br />&nbsp; &nbsp; &nbsp; &nbsp; client *clt;<br />	clt = [[client alloc] init]];<br />	[mArrClients addObject:clt];<br />
    


    le client lui aussi par un évènement instancie un recieverController
    <br />	recieverController* rc=[[recieverController alloc] initWithMessage:msg andIP:mIP];<br />	[rc appear:msg];<br />
    


    voilà  le cheminement, en espérant que ça a pu apporter dautres renseignements.



    dans 1220634813:

    Je répète : là  est ton problème.

    Tu instancies un nouveau recieverController rc. Donc cx'est un nouvel objet vierge, avec tous ses outlets vides.



    Justement, outlets vides, comment peut-on les remplir?
    j'ai essayé pas mal de trucs mais j'ai pas l'impression qu'on peut le faire aisément.

    peut on instancier directement un objet de l'IB?
    par exemple

    MaFenetre* f

    qui comportera tous les composants intégrés (boutons, fields) etc...
  • NoNo Membre
    septembre 2008 modifié #8
    Ok, je comprends mieux.

    Alors voici la marche à  suivre : il te faut 2 nibs !

    Le premier, mainMenu contient le file's owner (qui repésente ton objet application) et dans ta classe principale app.

    Le second va juste contenir une fenêtre. Le file's owner de ce 2nd nib sera ta classe recieverController (dans IB, dépose ton .h sur le projet, puis ensuite via l'inspecteur, modifie la custom class du file's owner pour y mettre ta classe).
    Maintenant, tu peux lier la fenêtre avec les outlets du file's owner.

    Lorsque tu alloc/init ta classe recieverController pour obtenir rc, il faudra juste après charger le 2nd nib (donc ça chargera la fenêtre en mémoire) avec la méthode loadNibNamed:owner: de NSBunble par :
    <br />[NSBundle loadNibNamed:@&quot;le-nom-du-2nd-nib&quot; owner:rc];<br />
    

    Tous les objets du nib seront donc en mémoire. Le paramètre owner représente dans le nib le file's owner. Or tu y as lié tes outlets. Comme rc est le owner, donc ses outlets seront correctement initialisés.

    Voilà  le principe.

    Bien sûr, ta fenêtre peut contenir tout plein de contrôles, du moment que tous les outlets/actions sont reliés au file's owner, et que recieverController déclare bien ces outlets/actions.

    Ca parait lourdingue, mais je ne vois pas trop ce que tu veux faire avec ta fenêtre.
    Je suis sûr qu'il y a mieux à  faire.
  • neurosupherotneurosupherot Membre
    11:37 modifié #9
    ben en fait, c'est ce que j'avais fait au début et ça marchait...
    le problème... c'est qu'il y en avait un autre.

    Je voulais en appuyant sur un bouton de la fenêtre d'une 2ème nib, qu'il exécute une fonction d'un controlleur du 1er nib.

    plus en détails :
    recieverController est initialisé avec un nom

    je voudrais qu'en cliquant sur le bouton de la fenetre du 2ème nib, qu'il envoie le nom à  un controlleur du 1er nib.

    est-ce que ça existe des objets partagés?
  • NoNo Membre
    11:37 modifié #10
    Si au moment où tu fais le alloc/init de recieverController, tu connais le 1er contrôleur, alors pas de problème.
    Ajoute dans le @interface de recieverController une variable de type id.
    Créé les accesseurs pour alimenter cette variable avec l'id de ton 1er contrôleur.

    Si je me réfere au code plus haut, ton 1er contrôleur semble être scont.
    De plus, c'est dans scont que tu sembles faire le alloc/init de recieverController.

    Donc, fais quelque chose comme ça :

    dans recieverController :
    <br />@interface recieverController:NSObject<br />{<br />id _scont;<br />}<br />- (void)setSCOnt:(id)aSContObject;<br />@end<br /><br />@implementation recieverController<br />- (void)setSCOnt:(id)aSContObject<br />{<br />if (_scont) [_scont release];<br />_scont=aSContObject;<br />if (_scont) [_scont retain];<br />}<br />@end<br />
    


    puis dans scont :
    <br />recieverController* rc=[[recieverController alloc] initWithMessage:msg andIP:mIP];<br />[rc setSCont:self];<br />[rc appear:msg];<br />
    


    Maintenant, depuis rc tu pourras appeller n'importe quelle méthode de scont en faisant simplement :
    <br />if (_scont) [_scont executeUneMethode];<br />
    

  • neurosupherotneurosupherot Membre
    11:37 modifié #11
    C'est un peu du bricolage mais en tous cas ça marche impec, merci!!
  • NoNo Membre
    11:37 modifié #12
    dans 1220705440:

    C'est un peu du bricolage mais en tous cas ça marche impec, merci!!

    Pas vraiment un bricolage.
    C'est à  peu de chose le principe du mécanisme des delegates.
Connectez-vous ou Inscrivez-vous pour répondre.