Swift modal sheet: willPositionSheet does doesn't get called

659 Views Asked by At

I'm trying to set the position of a modal sheet in a ViewController. What I´ve got so far is this:

import Cocoa

class ViewController: NSViewController, NSWindowDelegate {

    func window(_ window: NSWindow, willPositionSheet sheet: NSWindow, using rect: NSRect) -> NSRect {
        print("function entered")
    }

    var sheetWindowController: SheetWindowController!

    @IBAction func showSheet(_ sender:AnyObject){
        let windowController = SheetWindowController(windowNibName: "SheetWindowController")
        self.sheetWindowController = windowController
        self.sheetWindowController.delegate = self
        self.view.window?.beginSheet(self.sheetWindowController.window!, completionHandler: nil)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        self.view.window?.delegate = self
    }
}

It is working as far as the sheet shows up on the top of the window. But the willPositionSheetmethod doesn't get called. Any idea what is missing?

1

There are 1 best solutions below

0
On BEST ANSWER

2 things.

First: Your view controller view's window property likely won't be nonnil until viewDidAppear() (you can verify by debugging with breakpoints whether the window is nonnil). So make sure that the delegate is actually set on the window. I'd also note that you might want to try leaving the window delegate tied to the window's controller object or a distinct window delegate object that is not owned by the view controller. The view controller is sort of an odd place to put this logic.

Second: Presenting a window that is owned by an NSWindowController doesn't seem to get these callbacks for some reason (I tested with just passing a standard NSWindow object and the delegate received the willPositionSheet call). Not sure why this is the case, but something with how these windows are setup I guess. With that said, you can try using the newer (10.10) NSViewController presentation APIs to make your life easier. I would try presenting an NSViewController using NSViewController's presentViewControllerAsSheet(_:).

So in summary you could have something like:

override func viewDidAppear() {
    super.viewDidAppear()
    self.view.window?.delegate = self
}

and for presenting:

let vc = SheetViewController() // Note this is a view controller, not window controller
presentViewControllerAsSheet(vc)

Hopefully that helps a bit.