Multiples Nib/Xib: modal view

6ix6ix Membre
04:46 modifié dans API AppKit #1
Hello tout le monde!

J'ai cherché partout, en français comme en anglais, mais je ne tombe jamais sur la solution... Mon application (non-document based) possède une fenêtre principale, avec son contrôleur, de laquelle on peut ouvrir 2 fenêtres secondaires. Celles-ci sont créées dans 2 autres xib, dont le File's owner est une instance de 2 autres classes dérivant de NSWindowController. En résumé: 3 fenêtres, 3 xib, 3 contrôleurs.

Dans mon MainController, j'ai 2 IBOutlet vers les 2 autres contrôleurs, AController et BController. Le File's Owner du xib AWindow est donc défini en tant que AController, et la variable window est bien connectée à  la fenêtre.

Mon but est d'afficher depuis ma fenêtre principale la fenêtre A en tant que modal view, mais j'obtiens une erreur.

Voici le code dans MainController:
<br />- (IBAction)showAddUserPanel:(id)sender {<br />	[NSApp beginSheet:[AController window] modalForWindow:self.window modalDelegate:nil didEndSelector:nil contextInfo:nil];<br />}<br />


et l'erreur:

*** Assertion failure in -[NSApplication _commonBeginModalSessionForWindow:relativeToWindow:modalDelegate:didEndSelector:contextInfo:], /SourceCache/AppKit/AppKit-949.43/AppKit.subproj/NSApplication.m:3031
Modal session requires modal window


Cette erreur provient du fait que [AController window] vaut nil. Mais je ne vois pas pourquoi, puisque AController est déclaré en tant que IBOutlet et window est bien connecté dans IB?

Sûrement un oubli ou une erreur bête de ma part, mais je sèche...! Merci de votre aide =)

Réponses

  • FloFlo Membre
    mars 2009 modifié #2
    Est-tu sur d'avoir indiquer le bon windowNibName dans la méthode initWithWindowNibName? Il ne faut pas mettre l'extension dans le nom du fichier et respecter la casse...

    Ou sinon, j'ai déjà  eu un bug bizarre de ce genre parce que j'avais localiser mon xib/nib... si tel est ton cas, essaye de le délocaliser et de relancer ton appli.
  • Philippe49Philippe49 Membre
    04:46 modifié #3
    dans 1237643078:

    Modal session requires modal window

    Manifestement il ne trouve pas la fenêtre

    dans 1237643078:

    ... Mon application (non-document based) possède une fenêtre principale, avec son contrôleur, de laquelle on peut ouvrir 2 fenêtres secondaires. Celles-ci sont créées dans 2 autres xib, dont le File's owner est une instance de 2 autres classes dérivant de NSWindowController. En résumé: 3 fenêtres, 3 xib, 3 contrôleurs.

    Dans mon MainController, j'ai 2 IBOutlet vers les 2 autres contrôleurs, AController et BController. Le File's Owner du xib AWindow est donc défini en tant que AController, et la variable window est bien connectée à  la fenêtre.


    Comment AController sait-il qu'il doit utiliser le xib AWindow.xib pour trouver sa fenêtre?

    Autrement dit utilises-tu la méthode initWithWindowNibName pour initialiser AController, ou as-tu simplement mis un objet AController dans ton nib principal ?
  • Philippe49Philippe49 Membre
    04:46 modifié #4
    Dans le cas où tu mets des outlets dans le nib principal :

    @implementation AWindowController
    - (NSString *)windowNibName {
    return @AWindow;
    }
    @end
  • 6ix6ix Membre
    mars 2009 modifié #5
    dans 1237648930:

    Dans le cas où tu mets des outlets dans le nib principal :

    @implementation AWindowController
    - (NSString *)windowNibName {
    return @AWindow;
    }
    @end


    Merci, ça marche comme ça! Ou disons presque, car la fenêtre ne "glisse" pas par dessus la fenêtre appelante, mais s'affiche totalement ailleurs!*

    J'avais fait avec la méthode initWithWindowNibName, mais si je comprends bien cette méthode n'est pas du tout appelée si AController est défini en tant qu'IBOutlet et pas spécifiquement créé "à  la main"?

    *Ce qui est étrange, c'est que si je clique sur cancel et ouvre à  nouveau la fenêtre, elle s'affiche alors normalement en tant que fenêtre modale.

    Cancel appelle cette méthode dans AController:
    <br />- (IBAction)cancel:(id)sender {	<br />	[self.window orderOut:self];<br />	[NSApp endSheet:self.window];<br />}<br />
    
  • Philippe49Philippe49 Membre
    mars 2009 modifié #6
    Dans IB, décocher "Visible At Launch"


    Dans le contrôleur principal,

    #import &quot;AppController.h&quot;<br />#import &quot;AWindowController.h&quot;<br /><br />@implementation AppController<br /><br />-(IBAction) showSheetWindow:(id)sender {<br />	[NSApp beginSheet:[aWC window] modalForWindow:window modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:nil];<br />}<br />- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo {<br />	NSLog(@&quot;sheet did end&quot;);<br />	[[aWC window] orderOut:self];<br />}<br /><br />@end
    



    Dans le AWindowController

    #import &quot;AWindowController.h&quot;<br /><br /><br />@implementation AWindowController<br />- (NSString *)windowNibName {<br />	return @&quot;AWindow&quot;;<br />}<br />-(IBAction) stopSheet:(id) sender {<br />	[NSApp endSheet:[self window] returnCode:NSOKButton];<br />}<br />@end<br />
    
  • 6ix6ix Membre
    04:46 modifié #7
    C'est en ordre, merci!

    Cela dit, le [aWC loadWindow] n'est jamais appelé; est-ce simplement un test "au cas où"? Et dans ce cas, dans quel cas la fenêtre n'est-elle pas chargée?
    C'est d'ailleurs bizarre, vu que justement mon 1er problème était que sa valeur était nil.
  • Philippe49Philippe49 Membre
    04:46 modifié #8
    dans 1237718235:

    Cela dit, le [aWC loadWindow] n'est jamais appelé; est-ce simplement un test "au cas où"? Et dans ce cas, dans quel cas la fenêtre n'est-elle pas chargée?
    C'est d'ailleurs bizarre, vu que justement mon 1er problème était que sa valeur était nil.


    Effectivement, le simple fait de mettre [aWC window] provoque le chargement du nib associé (il suffit de mettre un NSLog dans la méthode windowNibName:)
    Cela fait partie des mécanismes sous le capot , et on peut supprimer le chargement [aWC loadWindow] :

    Doc de NSWindowController

    window
    Returns the window owned by the receiver.

    - (NSWindow *)window

    Return Value
    The window owned by the receiver or nil if there isn't one.

    Discussion
    If the window has not yet been loaded, this method attempts to load the window's nib file using loadWindow. Before it loads the window, it invokes windowWillLoad, and if the window controller has a document, it invokes the document's corresponding method windowControllerWillLoadNib: (if implemented). After loading the window, this method invokes windowDidLoad and, if there is a document, the NSDocument method windowControllerDidLoadNib: (if implemented).


    En regardant la doc sur loadWindow, on voit aussi que l'on peut redéfinir la méthode loadWindow au lieu de windowNibName.
  • FloFlo Membre
    04:46 modifié #9
    Les controlleurs qui sont instanciés dans un nib (et pas à  la mano) sont initialisés avec la méthode initWithCoder: (NScoder *)coder car le nib/xib est une archive. Il n'y a donc pas d'appel à  la méthode initWithWindowNibName: ce qui t'oblige à  charger le nib par un appel explicite (à  loadWindow par exemple). Ce qu'on gagne d'un côté, on le perd de l'autre  ;)
Connectez-vous ou Inscrivez-vous pour répondre.