NSBundle et XIB

RadadaRadada Membre
23:44 modifié dans API AppKit #1
Salut à  tous  ;)

me revoilà  avec un pb à  la con!!!
Dans un bouquin de prog Cocoa (celui de Aaron Hilleglass pour ne pas le citer ^^), il y a des exos. Mais ceux ci ne sont pas corrigés (ce qui peut être chiant quand on bloque sur un comme c'est le cas pour moi aujourd'hui)...

Voici la problématique. J'ai une classe AppController qui contient 2 outlets : un vers une autre classe PreferenceController (qui dérive de WindowController) et un autre vers un NSPanel (aboutPanel).
But de l'exo : afficher la fenêtre 'A propos' (About.xib) en utilisant le NSbundle et notamment (enfin, j'imagines) loadNibNamed: owner:. Pour cela, j'ai une méthode showAboutPanel...
Si j'arrive bien à  afficher la fenêtre en utilisant un [NSBundle loadNibNamed:@About owner:self], je n'arrive pas à  trouver comment faire "pointer" (déformation du CPP :D) l'outlet vers l'instance du NSPanel créé par loadNibNamed.
J'ai essayé de mettre mon outlet comme owner du loadNibNamed, mais ça plante. Si j'sintancie un nouveau NSPanel avant d'appeler [NSBundle loadNibNamed:@About owner: aboutPanel], ça ne plante pas, mais quand je repasse dedans, impossible d'afficher le aboutPanel...

Vala, je suis perdu  :-\\ :-\\

Merci d'avance, en espérant que ce soir clair. : )

Réponses

  • CéroceCéroce Membre, Modérateur
    juin 2009 modifié #2
    dans 1244807194:

    J'ai une classe AppController qui contient 2 outlets


    Non, ce ne sont pas des Outlets. Ce sont de simples références (des pointeurs).
    Les Outlets sont précédées d' IBOutlet dans leur déclaration et peuvent être reliées dans IB.


    Charger le XIB avec [NSBundle loadNibNamed:owner:] va instancier tous les objets présents dans le XIB => Pas de NSPanel à  instancier à  la mano.


    Il faut que tu aies un XIB par NSWindow ou NSPanel. Pour pouvoir appeler -[NSWindowController initWithWindow:], il faut que l'AppDelegate possède une outlet aboutPanel vers le NSPanel.
    Dans About.xib, mets la classe de File's Owner à  AppDelegate pour voir apparaà®tre l'outlet aboutPanel, et relie le panneau.

    Relis la partie consacrée au chargement de Preferences.xib dans la livre, la procédure est très similaire.
  • RadadaRadada Membre
    23:44 modifié #3
    Salut Ceroce et merci pour ta réponse :)

    Alors au temps pour moi : pour le PreferenceController, c'est bien un pointeur, mais pour le aboutPanel, ils parlent bien d'Outlets (avec IBOutlet donc, et lien dans IB).
    J'avais effectivement pensé à  utiliser un NSWindowController, mais ils disent bien d'utiliser la classe NSBundle pour charger le fichier NIB (XIB en l'occurence) et que l'outlet pointe ensuite sur la fenêtre nouvellement créée.

    Du coup je suis paumé, puisque loadNibNamed charge le fichier NIB et l'affiche, mais ne renvoie en rien un pointeur vers l'instance de cette fenêtre...

    pas glop?


    dans 1244809819:

    dans 1244807194:

    J'ai une classe AppController qui contient 2 outlets


    Non, ce ne sont pas des Outlets. Ce sont de simples références (des pointeurs).
    Les Outlets sont précédées d' IBOutlet dans leur déclaration et peuvent être reliées dans IB.


    Charger le XIB avec [NSBundle loadNibNamed:owner:] va instancier tous les objets présents dans le XIB => Pas de NSPanel à  instancier à  la mano.


    Il faut que tu aies un XIB par NSWindow ou NSPanel. Pour pouvoir appeler -[NSWindowController initWithWindow:], il faut que l'AppDelegate possède une outlet aboutPanel vers le NSPanel.
    Dans About.xib, mets la classe de File's Owner à  AppDelegate pour voir apparaà®tre l'outlet aboutPanel, et relie le panneau.

    Relis la partie consacrée au chargement de Preferences.xib dans la livre, la procédure est très similaire.
  • CéroceCéroce Membre, Modérateur
    23:44 modifié #4
    dans 1244817534:

    Du coup je suis paumé, puisque loadNibNamed charge le fichier NIB et l'affiche, mais ne renvoie en rien un pointeur vers l'instance de cette fenêtre...


    C'est pour cela que l'AppDelegate doit posséder une outlet aboutPanel et qu'on en fait le owner du fichier nib, lors de l'appel à  -[NSBundle loadNibNamed:owner:].

    Relis ce que j'ai écris, tout y est " dans le désordre ! " mais tout y est  ;)
  • laudemalaudema Membre
    23:44 modifié #5
    dans 1244807194:

    Salut à  tous  ;)


    Si j'arrive bien à  afficher la fenêtre en utilisant un [NSBundle loadNibNamed:@About owner:self], je n'arrive pas à  trouver comment faire "pointer" (déformation du CPP :D) l'outlet vers l'instance du NSPanel créé par loadNibNamed.
    J'ai essayé de mettre mon outlet comme owner du loadNibNamed, mais ça plante. Si j'sintancie un nouveau NSPanel avant d'appeler [NSBundle loadNibNamed:@About owner: aboutPanel], ça ne plante pas, mais quand je repasse dedans, impossible d'afficher le aboutPanel...

    Vala, je suis perdu  :-\\ :-\\

    Merci d'avance, en espérant que ce soir clair. : )

    Si je reprends le bouquin il dit de mettre AppController propriétaire du nib, tu peux faire ça dans IB et le xib ou mettre owner:self (self étant l'instance de AppController qui est en train de lancer le xib).

    Si tu mets AppController fileOwner dans IB et que tu as déclaré un IBOutlet NSPanel *aboutPanel dans AppController, tirer un lien bleu entre fileOwner et aboutPanel ne devrait pas être bien difficile ;)

  • RadadaRadada Membre
    23:44 modifié #6
    Le fait d'établir un lien dans IB permet d'indiquer que l'outlet va pointer sur une instance de la fenêtre. Mais lorsque j'instancie cette fenêtre sans indiquer explicitement au système de pointer sur cet espace mémoire, je ne pense pas qu'il le fasse de lui même si?

    Je la refait, j'ai pas l'impression d'être clair  :P

    Tu peux avoir un IBOutlet NSPanel*, tirer un lien dans IB, cela ne signifie pas que ton pointeur va effectivement pointer sur l'instance en mémoire du NSPanel si d'une façon ou d'una autre tu ne passe pas ton pointeur en argument de la fonction. Dans [NSBundle loadNibNamed:@About owner:self], à  aucun moment je n'indique au système que la fenêtre qui va être créée par le NSBundle est celle qui est pointée par mon Outlet. Ou alors IB et Cocoa sont monstrueusement balaise (ce dont je ne doute pas ceci dit :D:D)

    La je suis sur la partie "Exo" à  la fin du chapitre hein, pas sur le chapitre Préférence controller :)

    dans 1244823117:

    dans 1244807194:

    Salut à  tous  ;)


    Si j'arrive bien à  afficher la fenêtre en utilisant un [NSBundle loadNibNamed:@About owner:self], je n'arrive pas à  trouver comment faire "pointer" (déformation du CPP :D) l'outlet vers l'instance du NSPanel créé par loadNibNamed.
    J'ai essayé de mettre mon outlet comme owner du loadNibNamed, mais ça plante. Si j'sintancie un nouveau NSPanel avant d'appeler [NSBundle loadNibNamed:@About owner: aboutPanel], ça ne plante pas, mais quand je repasse dedans, impossible d'afficher le aboutPanel...

    Vala, je suis perdu  :-\\ :-\\

    Merci d'avance, en espérant que ce soir clair. : )

    Si je reprends le bouquin il dit de mettre AppController propriétaire du nib, tu peux faire ça dans IB et le xib ou mettre owner:self (self étant l'instance de AppController qui est en train de lancer le xib).

    Si tu mets AppController fileOwner dans IB et que tu as déclaré un IBOutlet NSPanel *aboutPanel dans AppController, tirer un lien bleu entre fileOwner et aboutPanel ne devrait pas être bien difficile ;)
  • RadadaRadada Membre
    23:44 modifié #7
    Yo grand waza :p

    Effectivement, si je relis (et je comprend, ce qui est moins sur  ;D), il suffirait d'appeler [NSBundle loadNibNamed: owner] en passant le IBOutlet en owner pour indiquer que l'owner du NSPanel est l'IBOutlet?
    Si c'est ça, j'avais fait ça au début, mais le prg explose sur un index out of bounds ou un truc comme ça. D'où l'idée : le NSPanel* est null, et peut être qu'il faut passer un objet non nil à  loadNibNamed.

    Dis moi si c'est que tu voulais dire ou si, une fos n'est pas coutume, j'ai compris de travers  ;D ;D ;D

    Merci grand chef



    dans 1244818441:

    dans 1244817534:

    Du coup je suis paumé, puisque loadNibNamed charge le fichier NIB et l'affiche, mais ne renvoie en rien un pointeur vers l'instance de cette fenêtre...


    C'est pour cela que l'AppDelegate doit posséder une outlet aboutPanel et qu'on en fait le owner du fichier nib, lors de l'appel à  -[NSBundle loadNibNamed:owner:].

    Relis ce que j'ai écris, tout y est " dans le désordre ! " mais tout y est  ;)
  • CéroceCéroce Membre, Modérateur
    juin 2009 modifié #8
    Non, l'énoncé de l'exo dit clairement qu'il faut que l'AppDelegate soit l'owner.

    Tu ne peux absolument pas passer l'outlet, puisque l'outlet vaut nil (= 0) tant que le NIB n'a pas été chargé. Et de toute façon, l'outlet sera de type NSPanel, et un NSPanel ne se gère pas lui-même, il faut un NSWindowController.

    Dans un 1er temps, essaie de charger le panneau About de la même façon que la fenêtre Préférences. Quand ce sera au point, là  tu essaieras avec loadNibNamed. L'exercice n'est pas compliqué, vraiment, mais tu mélanges plein de concepts. Tâche de comprendre ce concept d'owner et son lien avec le File's Owner du fichier NIB.
  • RadadaRadada Membre
    23:44 modifié #9
    Bon je teste ça enrte midi et deux alors.
    J'ai pas tout suivi, mais je vais essayer.
    En fait je pense trop en C++ je pense, et pas assez en Cocoa/Objective-C j'ai l'impression...
    @cet AM donc ;D;D
    Merci Céroce.

    dans 1245057668:

    Non, l'énoncé de l'exo dit clairement qu'il faut que l'AppDelegate soit l'owner.

    Tu ne peux absolument pas passer l'outlet, puisque l'outlet vaut nil (= 0) tant que le NIB n'a pas été chargé. Et de toute façon, l'outlet sera de type NSPanel, et un NSPanel ne se gère pas lui-même, il faut un NSWindowController.

    Dans un 1er temps, essaie de charger le panneau About de la même façon que la fenêtre Préférences. Quand ce sera au point, là  tu essaieras avec loadNibNamed. L'exercice n'est pas compliqué, vraiment, mais tu mélanges plein de concepts. Tâche de comprendre ce concept d'owner et son lien avec le File's Owner du fichier NIB.
  • RadadaRadada Membre
    23:44 modifié #10
    Putain j'ai regardé, je dois être une quiche...
    J'ai checké le File's Owner du About.xib, c'est bien le AppController. L'Outlet est ok, le lien est bien fait.
    Ensuite, j'ai essayé (comme pour faire dans l'exo) de créer une classe AboutController qui dérive de NSWindowController, en faire le File's Owner du fichier XIB et tout, mais ça marche po non plus...
    Je continue demain, sinon je passe à  autre chose  :-\\

    dans 1245057668:

    Non, l'énoncé de l'exo dit clairement qu'il faut que l'AppDelegate soit l'owner.

    Tu ne peux absolument pas passer l'outlet, puisque l'outlet vaut nil (= 0) tant que le NIB n'a pas été chargé. Et de toute façon, l'outlet sera de type NSPanel, et un NSPanel ne se gère pas lui-même, il faut un NSWindowController.

    Dans un 1er temps, essaie de charger le panneau About de la même façon que la fenêtre Préférences. Quand ce sera au point, là  tu essaieras avec loadNibNamed. L'exercice n'est pas compliqué, vraiment, mais tu mélanges plein de concepts. Tâche de comprendre ce concept d'owner et son lien avec le File's Owner du fichier NIB.
  • RadadaRadada Membre
    23:44 modifié #11
    Yo grand : )

    Je ne piges plus rien.
    J'ai trouvé ce post sur le net : http://www.omnigroup.com/mailman/archive/macosx-dev/2000-July/015147.html
    Il s'avère que, hormis la méthode orderFront, c'est ce que je faisais jusqu'à  présent (y compris les owner et File's owner), mais cela ne fonctionne pas.

    Lors du second appel de showAboutPanel, je pars en erreur avec gdb.

    Comme indiqué dans l'exo, j'ai bien mis un Outlet dans AppController, le File's Owner du About.xib est AppController, le lien est bien fait entre l'Outlet et le NSPanel. Bref, il me semble y avoir tout...

    Y'a moyen de poster le code quelque part si tu me dire ce qu'il manque parce que je crise là   :'( :'(

    Merci chief.

    dans 1245057668:

    Non, l'énoncé de l'exo dit clairement qu'il faut que l'AppDelegate soit l'owner.

    Tu ne peux absolument pas passer l'outlet, puisque l'outlet vaut nil (= 0) tant que le NIB n'a pas été chargé. Et de toute façon, l'outlet sera de type NSPanel, et un NSPanel ne se gère pas lui-même, il faut un NSWindowController.

    Dans un 1er temps, essaie de charger le panneau About de la même façon que la fenêtre Préférences. Quand ce sera au point, là  tu essaieras avec loadNibNamed. L'exercice n'est pas compliqué, vraiment, mais tu mélanges plein de concepts. Tâche de comprendre ce concept d'owner et son lien avec le File's Owner du fichier NIB.
  • CéroceCéroce Membre, Modérateur
    23:44 modifié #12
    Oui, zippe le dossier projet et mets-le ici en pièce jointe. Pense à  virer le dossier Build avant.
  • RadadaRadada Membre
    23:44 modifié #13
    un trèèèèèèèèèèèèèèèèèès grand merci à  toi chief.
    Je sens que je vais avoir honte quand tu vas me répondre ;D;D;D

    dans 1245155419:

    Oui, zippe le dossier projet et mets-le ici en pièce jointe. Pense à  virer le dossier Build avant.
  • mpergandmpergand Membre
    juin 2009 modifié #14
    Ouais, un grand classique  ;)

    Décoche: Release when closed dans IB pour le panel !

    Le truc crétin c'est que c'est coché par défaut dans IB pour Leopard  ::)
  • CéroceCéroce Membre, Modérateur
    23:44 modifié #15
    Le problème c'est que tu n'utilises pas de NSWindowController pour charger le panneau About.
    La fenêtre des préférences, est gérée par PreferenceController qui hérite de NSWindowController.

    Il faut que tu fasses pareil avec le panneau About. La différence, c'est que AboutController aura une méthode -initWithPanel:(NSPanel*)panel au lieu de simplement -init.


    P.S.: Il y a une autre méthode possible, à  laquelle mpergand fait référence. On peut cocher la case Visible at launch du NSPanel. Dans ce cas, le panneau sera visible dès le chargement du NIB. Il faut aussi décocher Release when Closed dans ce cas, sinon le panneau est retiré de la mémoire dès qu'on ferme la fenêtre. C'est un méthode qui convient pour un panneau About (pas de gestion du panneau à  faire, donc pas besoin de NSWindowController), mais je crois que ce n'est pas l'esprit de l'exercice.
  • RadadaRadada Membre
    23:44 modifié #16
    Nan sérieux??? Je me case le cul depuis une semaine pour une case à  cocher????  ;D  ;D  ;D  ;D  ;D
    Eh bé, encore heureux que t'es là  Céroce, parce que je ne l'aurais pas trouvé tout seul celle là 
    Merci de tout coeur, t'es unn chef  :P :P


    dans 1245163048:

    Ouais, un grand classique  ;)

    Décoche: Release when closed dans IB pour le panel !

    Le truc crétin c'est que c'est coché par défaut dans IB pour Leopard  ::)
Connectez-vous ou Inscrivez-vous pour répondre.