'How do I set the minimum window size with swiftUI, and how do I make the window use the specified size and position when launching?

I am making a macOS app with swiftUI. I want to set the minimum size of the window to 800, 500. Also there is this thing that if I close the window, and reopen, it reopens as the size an position from when it last closed. How do I make it not remember the window position and size from when it last closed. I am using Xcode 11.2.1 and macOS Catalina, and I am making an app for macOS, not iOS. How can I do these two things?



Solution 1:[1]

If you created project from template for macOS SwiftUI based, then all changes you need to do is in AppDelegate.swift.

The size of window is content-defined, so you need to specify root content view frame, and to disallow window position saving you need to remove setFrameAutosaveName, as a result your AppDelegate should look like the following

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    var window: NSWindow!

    func applicationDidFinishLaunching(_ aNotification: Notification) {
        // Create the SwiftUI view that provides the window contents.
        let contentView = ContentView()
            .frame(minWidth: 800, maxWidth: .infinity, minHeight: 500, maxHeight: .infinity)

        // Create the window and set the content view. 
        window = NSWindow(
            contentRect: NSRect(x: 0, y: 0, width: 800, height: 500),
            styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
            backing: .buffered, defer: false)
        window.center()
        window.contentView = NSHostingView(rootView: contentView)
        window.makeKeyAndOrderFront(nil)
    }
    ...

Update: for SwiftUI life-cycle approach is the same - set frame to content view in window scene, like

var body: some Scene {
    WindowGroup {
        ContentView()
            .frame(minWidth: 800, maxWidth: .infinity, minHeight: 500, maxHeight: .infinity)
    }
}

backup

Solution 2:[2]

Newer versions of Xcode (and template) now use SwiftUI App life cycle, as opposed to the AppKit App Delegate. In that case, you case can set the window size (or the size of any SwiftUI View) using the Layout.frame method to setup your boundaries. Just like you would with any modifier:

    VStack {
        Text("You are Logged In")
        Button(action: {
            self.loggedIn = false
        }, label: {
            Text("Logout")
        })
    }
    .frame(minWidth: 400, idealWidth: 600, minHeight: 450, idealHeight: 800)

Again, this can be used with any SwiftUI View, so it's a handy way to layout your views.

Edit: This answer applies to all platforms, including macOS.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 RobMac