最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

swift - Window position for SwiftUI hosted view in MacOS Storyboard app - Stack Overflow

programmeradmin4浏览0评论

I'm trying new create some new windows using SwiftUI in my older MacOS app that uses Storyboards. It works pretty well, however, I'm unable to position the window on the screen. It seems there is some kind of conflict in coordinates system.

If I just use window.center() then it positions the top left corner to the center horizontally (not the center of the window is in the center of the screen, but the corner itself is in the center), and at the top vertically (right below menu bar).

If I use window.setFrameTopLeftPoint(.init(x: 0, y: 0)) then it sets the bottom left point instead. It seems some kind of reverted coordinate system? How do I make it work with AppKit?

Here is my SwiftUI window creation code (runs from Storyboard created window):

@IBAction func onButtonClicked(_ sender: Any) {
    let window = NSWindow(
        contentRect: .init(origin: .zero, size: .init(width: 400, height: 400)),
        styleMask: [.titled, .closable],
        backing: .buffered,
        defer: false
    )

    window.title = "Child SwiftUI Window"
    // window.center()
    window.setFrameTopLeftPoint(.init(x: 100, y: 100))

    // Use the class property instead of local variable
    let windowController = NSWindowController(window: window)
    windowController.contentViewController = ChildHostingController()!
    windowController.showWindow(nil)
}

SwiftUI view + hosting controller:

class ChildHostingController: NSHostingController<SwiftUITestView> {
    required init?(coder: NSCoder) {
        super.init(coder: coder,
                   rootView: SwiftUITestView())
    }
    required init?() {
        super.init(rootView: SwiftUITestView())
    }
}

struct SwiftUITestView: View {
    var body: some View {
        VStack { 
            Spacer()
            Text("This is a child window from SwiftUI")
            Spacer()
        }
        .padding(20)
        .frame(width: 400, height: 400)
    }
}

I'm trying new create some new windows using SwiftUI in my older MacOS app that uses Storyboards. It works pretty well, however, I'm unable to position the window on the screen. It seems there is some kind of conflict in coordinates system.

If I just use window.center() then it positions the top left corner to the center horizontally (not the center of the window is in the center of the screen, but the corner itself is in the center), and at the top vertically (right below menu bar).

If I use window.setFrameTopLeftPoint(.init(x: 0, y: 0)) then it sets the bottom left point instead. It seems some kind of reverted coordinate system? How do I make it work with AppKit?

Here is my SwiftUI window creation code (runs from Storyboard created window):

@IBAction func onButtonClicked(_ sender: Any) {
    let window = NSWindow(
        contentRect: .init(origin: .zero, size: .init(width: 400, height: 400)),
        styleMask: [.titled, .closable],
        backing: .buffered,
        defer: false
    )

    window.title = "Child SwiftUI Window"
    // window.center()
    window.setFrameTopLeftPoint(.init(x: 100, y: 100))

    // Use the class property instead of local variable
    let windowController = NSWindowController(window: window)
    windowController.contentViewController = ChildHostingController()!
    windowController.showWindow(nil)
}

SwiftUI view + hosting controller:

class ChildHostingController: NSHostingController<SwiftUITestView> {
    required init?(coder: NSCoder) {
        super.init(coder: coder,
                   rootView: SwiftUITestView())
    }
    required init?() {
        super.init(rootView: SwiftUITestView())
    }
}

struct SwiftUITestView: View {
    var body: some View {
        VStack { 
            Spacer()
            Text("This is a child window from SwiftUI")
            Spacer()
        }
        .padding(20)
        .frame(width: 400, height: 400)
    }
}
Share Improve this question asked Feb 15 at 17:33 SoidSoid 2,8612 gold badges33 silver badges45 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

I suspect this is related to how the hosting controller determines the size of the SwiftUI view, and the window receives an incorrect size when it tries to position itself on centered the screen.

By trial and error, I found that using .preferredContentSize as the sizingOptions fixes this. You can set it in the initialiser of ChildHostingController

required init?() {
    super.init(rootView: SwiftUITestView())
    sizingOptions = .preferredContentSize
}

Then calling window.center() like you did in your code works correctly.

Alternatively, you can also set the size of the hosting controller's view directly, but only if you know the size of the SwiftUI view beforehand.

super.init(rootView: SwiftUITestView())
view.setFrameSize(.init(width: 400, height: 400))
发布评论

评论列表(0)

  1. 暂无评论