You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI macOS应用:新窗口无法恢复用户上次设置尺寸问题

解决macOS SwiftUI窗口记忆尺寸问题

你的需求完全可以实现,问题出在用SwiftUI的.frame修饰符控制窗口尺寸的思路不对——.frame是用来约束视图内容的尺寸,而非直接控制窗口本身的初始大小,所以idealWidth/Height会被窗口的默认行为覆盖,优先使用最小尺寸。

正确的做法是直接在WindowGroup层面配置窗口的初始尺寸和最小限制,结合@AppStorage存储的用户自定义尺寸,同时确保初始尺寸不低于最小要求:

修改后的完整代码

import SwiftUI

@main
struct so_RememberWindowSizeApp: App {
    @AppStorage("windowSizeHeight") var windowSizeHeight = 800.0
    @AppStorage("windowSizeWidth") var windowSizeWidth = 1280.0
    
    // 确保存储的尺寸不小于最小值
    private var defaultWindowWidth: Double { max(windowSizeWidth, 1280) }
    private var defaultWindowHeight: Double { max(windowSizeHeight, 800) }

    var body: some Scene {
        WindowGroup {
            ContentView()
                .overlay {
                    GeometryReader { proxy in
                        Color.clear
                            .onAppear {
                                print("👀 Startup Width: \(proxy.size.width), Startup Height: \(proxy.size.height)")
                            }
                            .onChange(of: proxy.size) { _, newValue in
                                // 更新存储时同样确保不低于最小值
                                windowSizeHeight = max(newValue.height, 800)
                                windowSizeWidth = max(newValue.width, 1280)
                                print("👀 New Width: \(windowSizeWidth), New Height: \(windowSizeHeight)")
                            }
                    }
                }
        }
        // 设置窗口可调整性,并指定初始默认尺寸
        .windowResizability(.contentSize)
        .defaultSize(width: defaultWindowWidth, height: defaultWindowHeight)
        // 限制窗口最小尺寸
        .windowMinSize(width: 1280, height: 800)
    }
}

struct ContentView: View {
    @AppStorage("windowSizeHeight") var windowSizeHeight = 800.0
    @AppStorage("windowSizeWidth") var windowSizeWidth = 1280.0

    var body: some View {
        VStack(spacing: 32.0) {
            Text("Current Height in UserDefaults: \(windowSizeHeight)")
            Text("Current Width in UserDefaults: \(windowSizeWidth)")
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}

#Preview {
    ContentView()
}

关键改动说明

  • 移除.frame修饰符:不再用视图的frame约束窗口,转而直接配置WindowGroup的窗口属性
  • 添加窗口尺寸配置:
    • .windowMinSize:直接设置窗口的最小尺寸,确保窗口无法被拖到小于1280x800
    • .defaultSize:使用存储的尺寸(同时通过max确保不低于最小值)作为新窗口的初始大小
  • 更新存储逻辑:在保存用户调整的尺寸时,同样用max过滤掉小于最小值的情况,避免存储非法尺寸

这样修改后,Cmd+N打开新窗口时,会直接加载用户上次调整的尺寸(如果该尺寸≥1280x800),否则用最小尺寸,完全符合你的需求。

内容的提问来源于stack exchange,提问作者appfrosch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 13:20:31