windowDidLoad ne se lance pas...

Bonjour,



J'ai lu ici que je ne suis pas le seul à  me heurter à  ce problème. J'ai une fenêtre dans mon XIB avec un referencing outlet window bien lié à  mon controller, de même celui-ci est bien lié en tant que delegate, jusque là  tout va bien mais là  où ça se corse c'est que bien que ma fenêtre s'ouvre, visiblement le (void)windowDidLoad ne se lance pas... J'ai mis un NSLog pour être certain et ça confirme... Alors que le (id)initWithWindow:(NSWindow *)window fonctionne très bien...



C'est incompréhensible... Vous avez une solution ou une explication ?



Au passage ces 2 méthodes créées avec le windowController ne sont pas dans le .h, c'est normal j'imagine... bien que je ne sache pas pourquoi.



Merci de votre aide.

Réponses

  • CéroceCéroce Membre, Modérateur
    avril 2012 modifié #2
    'chaps31' a écrit:


    J'ai mis un NSLog


    Pourquoi mettre un NSLog() quand on peut mettre un point d'arrêt, qui lui, n'oblige pas à  recompiler ?


    'chaps31' a écrit:


    Vous avez une solution ou une explication ?


    Le chargement est fainéant. C'est à  dire que tant qu'on ne demande pas la fenêtre, elle n'est pas chargée.

    Tu peux le forcer en appelant [self window].

    C'est pour cela qu'il y a une méthode -isWindowLoaded.


    'chaps31' a écrit:


    Au passage ces 2 méthodes créées avec le windowController ne sont pas dans le .h,


    Dans quel .h ?
  • chaps31chaps31 Membre
    avril 2012 modifié #3
    le .h de mon windowController. Tu dis qu'une fenêtre peut s'afficher sans être chargée ?? .... Bigre...



    EDIT : le isWindowLoaded me confirme que ma fenêtre est bien chargée mais le windowDidLoad n'est pas lancé...



    ...bigre... Bon j'ai essayé close la fenêtre ne se ferme pas, donc j'ai essayé window et cela me retourne null... Donc pas de lien fait entre mon controller et ma fenêtre... Le lien : j'ai créé un objet de la classe de mon NSwindowController dans le XIB, il a un outlet "window" que j'ai lié dans le XIB à  la fenêtre, il y a erreur de ma part ? Merci.
  • CéroceCéroce Membre, Modérateur
    'chaps31' a écrit:


    Tu dis qu'une fenêtre peut s'afficher sans être chargée ?? .... Bigre...


    Non, je n'ai jamais dit ça. J'ai dit qu'il ne suffit pas d'initialiser un NSWindowController pour que sa fenêtre soit chargée.



    Essaie de décocher la case "Visible at Launch", j'ai des souvenirs de surprises avec.



    Essaie aussi d'implémenter la méthode:

    - (void) awakeFromNib

    dans ton contrôleur.

    Elle est appelée lorsque le nib est chargé.
  • chaps31chaps31 Membre
    avril 2012 modifié #5
    Le Visible at lauch n'a malheureusement rien changé. Ma fenêtre est un NSPanel, sous-classe de NSWindow je me doutais bien que ça ne changeait rien, mais m'arrachant les cheveux j'ai essayé en transformant en NSWindow, idem...



    Au bilan :

    window me retourne null, close me retourne null, mais la fenêtre est loadée... Vu mon statut d'amateur je suis certains que je fais une erreur tellement de base qu'elle ne te vient pas à  l'esprit...

    Donc la méthode : - (id)initWithWindow:(NSWindow *)window se lance bien mais avec window à  null... tout est là ... Pourquoi ? Dans mon XIB il y a un Outlet window pour mon windowcontroller (sans d'ailleurs d'IBOutlet dans le .h du windowcontroller) que je lie graphiquement à  mon NSPanel, cet Outlet est bien le "window" de la méthode précédente ?



    Merci encore...
  • CéroceCéroce Membre, Modérateur
    avril 2012 modifié #6
    Attends, comment instancies-tu le window controller ?

    Je veux voir DU CODE.
  • Le windowController est instancié dans le XIB... Pour l'instanciation du windowcontroller je ne vais pas pouvoir te sortir du code... image/wink.png' class='bbc_emoticon' alt=';)' />



    J'ai essayé le awakeFromNib : première désillusion le -close ne ferme pas la fenêtre par contre là  si je lui demande quelle fenêtre il contrôle c'est bon il m'indique mon NSPanel (toujours mes NSLog) alors qu'il m'indique null dans le - (id)initWithWindow:(NSWindow *)window et pareil dans - (void)windowDidLoad, si à  la limite dans le init peut-être n'a-t'il pas le temps de "percuter" image/wink.png' class='bbc_emoticon' alt=';)' /> le windowdidload qui ne se lance pas c'est incomprhensible....



    Au passage dans mon code je modifie un NSpopUpButton du NSPanel, évidemment ça ne marchait pas, mais dans le awakefromnib ça marche très bien... image/blink.png' class='bbc_emoticon' alt=' :o ' />
  • Bon ça marche en travaillant avec le awakeFromNib, merci, mais des choses me chagrinent...



    - Pourquoi le windowDidLoad ne marche pas...

    - J'ai oublié de déclarer dans le .h le awakeFromNib, mais ça ne pose pas de problème... idem pour le windowDidLoad qui n'est pas dans le .h ou le initWithWindow... Comment c'est possible ?



    Si vous avez des réponses, merci d'éclairer ma lanterne.
  • CéroceCéroce Membre, Modérateur
    'chaps31' a écrit:


    Le windowController est instancié dans le XIB... Pour l'instanciation du windowcontroller je ne vais pas pouvoir te sortir du code... image/wink.png' class='bbc_emoticon' alt=';)' />


    Il est là  ton problème. Un NSWindowController sert essentiellement à  charger un nib contenant une fenêtre.

    Donc, si tu l'instancies dans le nib, tu ne risques pas d'avoir la méthode -windowDidLoad appelée, puisqu'elle est déjà  chargée (les objets du nib ont été instanciés) !



    Utilise le Window Controller correctement:

    - Place la fenêtre seule dans un xib

    - Mets la classe du File's Owner à  ta sous-classe de NSWindowController

    - Relie l'outlet window

    - Instancie le window controller, par exemple dans l'AppDelegate:


    MyWindowController *windowController = [[MyWindowController alloc] initWithNibName:@"MyWindowController"];
    
  • Merci beaucoup je m'empresse de faire ça et de bien le digérer !
  • Quoique il y a un truc que je ne comprends pas...



    J'ai créé un objet dans le NIB, j'ai créé un windowController sous XCode et j'ai déclaré comme classe de mon objet dans le NIB mon windowcontroller créé dans XCode...

    Ce qui fait que je ne comprend pas pourquoi l'objet du Nib ne lance pas mon windowDidLoad, il est instancié à  partir de ma classe windowController, d'après ce que tu dis l'objet se chargerait avant la fenêtre...
  • CéroceCéroce Membre, Modérateur
    avril 2012 modifié #12
    Voir exemple ci-joint.



  • Merci encore, dès que j'ai 2 minutes j'analyse ça (là  je tape d'un PC...).
  • Bigre !!! J'ai testé, en effet, donc il ne faut pas créer de windowsController dans IB, c'est bizarre quand même...

    Merci encore.
  • CéroceCéroce Membre, Modérateur
    avril 2012 modifié #15
    Non, ce n'est pas bizarre. Un NSWindowController sert à  charger une fenêtre.

    Si tu as besoin d'un simple contrôleur, instancié dans le nib, fais-le hériter de NSObject et utilise -awakeFromNib.
  • OK, vraiment merci, juste deux petites questions :



    - On peut donc avoir des méthodes non déclarées dans le .h ?

    - Pourquoi self.windowcontroller dans l'AppDelegate, plus précisément pourquoi self. le windowcontroller est une variable d'instance de l'Appdelegate, on ne peut pas l'appeler directement sans le self. ?



    PS : ne pas oublier que c'est en posant des questions stupides qu'on l'est un peu moins image/wink.png' class='bbc_emoticon' alt=';)' />
  • Ho en lisant je réalise qu'une propriété n'est pas juste un moyen d'avoir automatiquement accesseur et mutateur et que self.lavar est la propriété tandis que lavar est la variable d'instance masquée dans la propriété... Argh... Va falloir que je trouve des infos pour éclaircir ces notions...
  • CéroceCéroce Membre, Modérateur
    'chaps31' a écrit:


    - On peut donc avoir des méthodes non déclarées dans le .h ?


    Il faut que les méthodes soient connues. À partir du moment où ton objet hérite de NSWindowController, il possède forcément une méthode windowDidLoad. Pas besoin de la redéclarer dans le .h.

    Note, que ça arrive quand même qu'on le fasse pour indiquer explicitement qu'on surcharge cette méthode.


    'chaps31' a écrit:


    - Pourquoi self.windowcontroller dans l'AppDelegate, plus précisément pourquoi self. le windowcontroller est une variable d'instance de l'Appdelegate, on ne peut pas l'appeler directement sans le self. ?


    Si, on peut. La différence c'est que
    self.windowController
    


    est équivalent à 
    [self windowController]
    


    tu passes donc par le getter.
  • OK, autre chose me chiffonne. Tu crée du coup un Xib par fenêtre ? Parce-que le :


    <br />
    self.secondWindowController = [[SecondWindowController alloc] initWithWindowNibName:@&quot;SecondWindowController&quot;];<br />
        [[self.secondWindowController window] orderFront:self];<br />
    




    Je comptais n'avoir qu'un Xib, c'est une erreur ?



    Ensuite tu lies le controller au xib mais cela ne définit pas à  quelle fenêtre... Donc pas le choix ? Un Xib par fenêtre ?



    Autre chose j'ai toujours lié mes IBOutlet dans IB, là ... comment faire si mon controller n'est pas instancié dans IB ?
  • chaps31chaps31 Membre
    avril 2012 modifié #20
    En réfléchissant sans doute un initWithWindow me permet de n'avoir qu'un seul Xib et spécifier la fenêtre, pour les IBoutlet je les déclare dans l'Appdelegate qui est présent dans IB et je crée les lien dans IB... Mais bigre tout mon code va être dans l'AppDelegate...



    Mais au final mieux vaut faire comme ça ou bien créer un Xib par fenêtre de l'application ?
  • CéroceCéroce Membre, Modérateur
    'chaps31' a écrit:


    Je comptais n'avoir qu'un Xib, c'est une erreur ?


    Oui et non.

    Il est possible de n'avoir qu'un seul XIB, mais ce n'est pas super astucieux parce que tous les objets qui sont dedans sont instanciés à  l'ouverture. Un cas concret est la fenêtre des préférences: finalement, on l'ouvre une fois tous les 20 lancements, alors pourquoi perdre du temps à  la charger si l'utilisateur ne s'en servira pas.



    Il y a une autre raison: avec un seul XIB, tu vas te retrouver avec un AppDelegate énorme.

    En fait, dans une appli un peu complexe, on utilise non seulement des NSWindowController avec un XIB pour chaque fenêtre, mais aussi des NSViewControllers pour gérer des vues qui vont être insérées dans une fenêtre.


    'chaps31' a écrit:


    Ensuite tu lies le controller au xib mais cela ne définit pas à  quelle fenêtre... Donc pas le choix ? Un Xib par fenêtre ?


    Pas le choix, le window controller ne peut gérer qu'une fenêtre. Il faut penser à  connecter son outlet window vers cette NSWindow.


    'chaps31' a écrit:


    Autre chose j'ai toujours lié mes IBOutlet dans IB, là ... comment faire si mon controller n'est pas instancié dans IB ?


    File's Owner (le cube orange dans le XIB) représente l'objet qui a ouvert le NIB. C'est à  lui que tu vas ajouter des outlets.
  • Merci beaucoup.
  • Bigre je m'inspire de ta création, je fais tout pareil sauf que je crée dans l'Appdelegate un IBOutlet window que je lie dans IB à  la fenêtre de mon controller (il y a 2 fenêtres). Mon controller est instancié dans l'AppDelegate (je l'ai viré du Xib) et là  je met ta ligne de code en remplaçant juste initWithWindowNibName par initWithWindow et en spécifiant en argument l'IBOutlet lié à  la fenêtre que mon controller doit gérer et ben... Le windowDidLoad n'est pas lancé à  nouveau... Si par contre je met le initWithWindowNibName impeccable le windowDidLoad est lancé... Arghhh...

    Je crois que je ne compends pas bien la nuance... le initWithWindowNibName est une méthode pour le windowController, mais si j'ai plusieurs fenêtre dans mon XIB comment sait-on laquelle est gérée par le controller ? Il y a définitivement un truc qui m'échappe... Je sens que tu vas me reparler du File's owner... image/wink.png' class='bbc_emoticon' alt=';)' />
  • CéroceCéroce Membre, Modérateur
    Le NSWindowController a une propriété window. C'est celle-là  qu'il gère.

    initWithWindow: sert si tu as déjà  créé la fenêtre par ailleurs et tu veux que le contrôleur la gère. C'est super rare de s'en servir.

    Fais un XIB par fenêtre.
  • OK.
  • C'est fait mais je ne vois pas comment lié ma fenêtre à  mon controller maintenant, par le File's owner ? Aucun Outlet... Bigre ce serait plus simple de faie les liens par IB... Là  je bloque, en lançant l'appli : une fenêtre "window" s'ouvre mais comment faire pour que ce soit celle que j'ai créé dans le XIB sans instancier mon controller dans le XIB... En plus étrange le pomme-Q reste en grisé dan sle menu de l'appli... Encore un coup de pouce ? Merci...
  • CéroceCéroce Membre, Modérateur
    • Instancie le window controller dans l'App Delegate et fais-lui charger le xib contenant la fenêtre.
    • Dans le xib contenant la fenêtre, la classe du File's Owner doit être mise à  celle de ton window controller (en haut, 3ème onglet, "Class"). N'oublie pas te tirer l'outlet window.
    • Passe en mode Assistant (noe“ud papillon). ça doit afficher le XIB et le window controller cote-à -cote. Tire les outlets du xib au window controller.
  • Merci beaucoup de ce cours Cocoa !!!
Connectez-vous ou Inscrivez-vous pour répondre.