jlagrone
jlagrone

Reputation: 86

Why would NSWindowController return nil-value window property?

I'm using modal sheets (slide down from top) to get user input. I currently have 2 that I think are identical except for the UI, each a NIB + NSWindowController-subclass pair. One works as expected, binding input to an array controller and table view. When trying to use the other, the window property of the NSWindowController is nil.

This code works:

      @IBAction func addItemButtonClicked(_ button: NSButton) {
      let window = document?.windowForSheet
      let windowController = NewItemSheetController()
      windowController.typeChoices = newItemSheetTypeChoices
      windowController.windowTitle = newItemSheetTitle

      print(#function, windowController.window) // output below
      window?.beginSheet(windowController.window!, completionHandler: { response in
         // The sheet has finished. Did user click OK?
         if response == NSApplication.ModalResponse.OK {
            let structure = (self.newItemSheetController?.structure)!
            self.document?.dataSource.structures.append(structure)
         }
         // All done with window controller.
         self.newItemSheetController = nil

      })
      newItemSheetController = windowController
   }

The output of the print statement: "addItemButtonClicked(_:) Optional()"

This code doesn't:

   @IBAction func addItemButtonClicked(_ button: NSButton) {
      let window = document?.windowForSheet
      let windowController = NewRecurrenceItemSheetController()
      windowController.windowTitle = newItemSheetTitle

      print(#function, windowController.window)
      window?.beginSheet(windowController.window!, completionHandler: { response in
         // The sheet has finished. Did user click OK?
         if response == NSApplication.ModalResponse.OK {
            let recurrence = (self.newItemSheetController?.recurrence)!
            self.document?.dataSource.recurrences.append(recurrence)
         }
         // All done with window controller.
         self.newItemSheetController = nil

      })
      newItemSheetController = windowController
   }

The output of the print statement: "addItemButtonClicked(_:) nil"

Classes NewItemSheetController and NewRecurrenceItemSheetController are subclasses of NSWindowController and differ only with NSNib.Name and properties related to differing UI. As far as I can see, the XIBs and Buttons are "wired" similarly. The XIBs use corresponding File's Owner. Window objects have default class.

@objcMembers
class NewItemSheetController: NSWindowController {

   /// other properties here

   dynamic var windowTitle: String = "Add New Item"

   override var windowNibName: NSNib.Name? {
      return NSNib.Name(stringLiteral: "NewItemSheetController")
   }

   override func windowDidLoad() {
      super.windowDidLoad()
      titleLabel.stringValue = windowTitle
   }

   // MARK: - Outlets

   @IBOutlet weak var titleLabel: NSTextField!
   @IBOutlet weak var typeChooser: NSPopUpButton!


   // MARK: - Actions

   @IBAction func okayButtonClicked(_ sender: NSButton) {
      window?.endEditing(for: nil)
      dismiss(with: NSApplication.ModalResponse.OK)
   }

   @IBAction func cancelButtonClicked(_ sender: NSButton) {
      dismiss(with: NSApplication.ModalResponse.cancel)
   }

   func dismiss(with response: NSApplication.ModalResponse) {
      window?.sheetParent?.endSheet(window!, returnCode: response)
   }
}

Why does one return instantiate a windowController object with a nil-valued window property?

Upvotes: 0

Views: 342

Answers (1)

jlagrone
jlagrone

Reputation: 86

In Interface Builder, the XIB Window needed to be attached to File's Owner with a Window outlet and delegate. Thanks @Willeke.

Upvotes: 0

Related Questions