How to show sheet from separate NIB

2019-04-06 17:03发布

问题:

How do I put a window in a separate NIB, give it its own NSWindowController, make it slide out as a sheet?

(Is this a typical thing to do with sheets?)

I am trying to show a custom sheet (a window that slides down from the title bar of the parent window) from my main window. What I'm trying to do is standard, I think, but I cannot find clear examples or explanations for how to do exactly what I want.

What I am trying to do:

  1. My app delegate owns the main window, which has a button to open a "settings" sheet.
  2. The "settings" sheet:
    • is in a separate NIB.
    • has file owner set to class SettingsWindowController, which is subclass of NSWindowsController
  3. When user clicks "settings", I am trying to use Apple's [sample code][1]
- (void)showCustomSheet: (NSWindow *)window
// User has asked to see the custom display. Display it.
{
    if (!settingsSheet) 
    //Check the settingsSheet instance variable to make sure the custom sheet does not already exist.
        [NSBundle loadNibNamed:@"SettingsSheet" owner: self];
        //BUT HOW DOES THIS MAKE settingsSheet NOT nil?

    [NSApp beginSheet: settingsSheet
            modalForWindow: window 
            modalDelegate: self 
            didEndSelector: @selector(didEndSheet:returnCode:contextInfo:) 
            contextInfo: nil]; 

    // Sheet is up here.

    // Return processing to the event loop
} 

Please excuse the following simplistic and numerous questions:

  • When I call, loadNibName:owner:, I don't want owner to be self, because that makes my app delegate the owner of the "MyCustomSheet" - that's what my SettingsWindowsController is supposed to be for. However, I don't know how make SettingsWindowsController the owner in this method.
  • If my sheet has "Visible at launch" checked, then loadNibName:owner: immediately displays the window as a normal window, not as a sheet that slides out from the main window.
  • If my sheet has "Visible at launch" not checked, then beginSheet:modalForWindow:etc causes "Modal session requires modal window". I'm pretty sure this is because I made the Nib's owner self (as I mentioned already).
  • In the sample code, I don't know how the Nib named @"SettingsSheet" is "associated" with the instance variable settingsSheet - but they apparently are related because the code checks first: if (!settingsSheet) (I've marked this with comment //BUT HOW DOES THIS MAKE settingsSheet NOT nil?)

Thanks for your patience in reading all this!

回答1:

  1. Create an instance of SettingsWindowController, use initWithWindowNibName:

  2. You don't want it visible at launch.

  3. See 1.

  4. Your instance variables will be available to SettingsWindowController