swiftswiftuiappkitnswindow

NSWindow is super tiny


I have a simple SwiftUI code to start a small NSWindow, like given below. However when the window appears, it's super small and ignores the minsize.

...
Button("Test Window") {
   let window = NSWindow(contentRect: NSRect(x: 0, y: 0, width: 800, height: 600),styleMask: [.titled, .closable, .resizable, .miniaturizable],backing: .buffered, defer: false)

   window.minSize = NSSize(width: 200, height: 400)
   window.title = "Test Window"
   window.contentView = NSHostingView(rootView: TestView())
   window.center()

   let windowController = NSWindowController(window: window)
   windowController.showWindow(self)
}
...

very tiny window


Solution

  • SwiftUI has a designated way of opening windows. Please do that if your app uses the SwiftUI lifecycle.


    SwiftUI sets up AutoLayout constraints on an NSHostingView based on the sizingOptions. The default value of this includes constraints for the minimum, maximum, and intrinsic content sizes of the SwiftUI view. The SwiftUI view you are using is very small, so the window ends up being very small.

    Also, setting NSWindow.contentView to an NSHostingView causes the window min size and max size to be determined by the SwiftUI view. From sizingOptions

    If the NSHostingView is set as the contentView of an NSWindow, it will also update the window’s contentMinSize and contentMaxSize based on the minimum and maximum size of its SwiftUI content.

    And as you may know, contentMinSize takes priority over minSize.

    To achieve the desired effect, I would set sizingOptions to only .minSize. Set the minimum size with a .frame modifier, since we don't control contentMinSize anymore.

    let host = NSHostingView(rootView: Text("Foo Bar Baz").frame(minWidth: 200, minHeight: 400))
    host.sizingOptions = .minSize
    window.contentView = host