macosswiftuicocoaappkit

NSWindow with SwiftUI content has zero frame on macOS 15


As title says. I create a window as such:

onboardWindow?.setFrame(.init(x: 0, y: 0, width: 600, height: 400), display: false)

Then, when it's time to show:

let contentView = WelcomeView()
let hostingVC = NSHostingController(rootView: contentView)
onboardWindow?.contentViewController = hostingVC

Before I set the contentViewController the frame is correct (the arbitrary values I set in the initialiser):

(0.0, 0.0, 600.0, 400.0)

After setting the contentViewController:

(0.0, 400.0, 0.0, 0.0)

Minified WelcomeView:

struct WelcomeView: View {

var body: some View {
    ZStack(alignment: .top) {
        Text("Hello, SO")
    }
    .frame(width: 600, height: 400)
    .background(Color.main)
  }
}

The window is displayed correctly (in terms of size and look), albeit at random position, because I cannot position a zero-sized frame.

Anyone came across this issue? This worked nicely on macOS 14 and lower. It broke on macOS 15 (Sequoia).


A hacky workaround: When I use contentView instead of contentViewController then it respects the initial frame I give it (600x400) but that requires me to duplicately set the size values both for the window initializer and the .frame() modifier on the SwiftUI view. I am going with this for now but I don't like it. Is there a way to define the size only in one place (preferrably in SwiftUI)?


Solution

  • I have been dealing with the same issue and found the solution on https://furnacecreek.org/blog/2024-12-07-centering-nswindows-with-nshostingcontrollers-on-sequoia

    Here is the OP's sample code with the one line fix added:

    let contentView = WelcomeView()
    let hostingVC = NSHostingController(rootView: contentView)
    onboardWindow?.contentViewController = hostingVC
    onboardWindow?.updateConstraintsIfNeeded() // fixes zero size issue