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

SwiftUI Mac多窗口应用状态恢复异常问题求助

SwiftUI Mac应用窗口状态恢复失败问题解决思路

问题描述

按照状态恢复原则,Mac应用重启后应自动恢复之前打开的窗口,但当前实现中,重启后恢复的窗口显示no person for you,无法正确显示之前的人物信息。

现有代码实现

主程序代码

@main
struct WindowTestApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        
        WindowGroup("Title", for: Person.ID.self){ $id in
            TestView(personID: $id)
        }
    }
}

窗口打开按钮代码

struct OpenWindowButton: View {
    @Environment(\.openWindow) var openWindow
    let person: Person
    
    var body: some View {
        Button("Open new window"){
            openWindow(value: person.id)
        }
    }
}

模型代码

struct Person:Identifiable, Hashable{
    
    let name: String
    let age: Int
    var id: UUID
}

let people:[Person] = [
    Person(name: "Jack", age: 41, id: UUID()),
    Person(name: "Mary", age: 32, id: UUID()),
    Person(name: "Linda", age: 18, id: UUID()),
    Person(name: "Joe", age: 13, id: UUID()),
    Person(name: "Kid", age: 1, id: UUID())
]

ContentView代码

struct ContentView: View {
    
    var body: some View {
        List{
            ForEach(people, id:\.self){person in
                VStack{
                    Text(person.name)
                }.contextMenu{
                    OpenWindowButton(person: person)
                }
            }
        }
    }
}

TestView代码

struct TestView: View {
    @Binding var personID: Person.ID?
    
    var body: some View {
        if let personFromID = people.first(where: {$0.id == personID}){
            VStack {
                Text(personFromID.name)
                Text("\(personFromID.age)")
            }
        }else{
            Text("no person for you")
        }
    }
}

解决思路

核心问题

重启后窗口无法匹配到对应Person的根本原因是:people数组中的每个Person的id是每次APP启动时重新生成的新UUID,而状态恢复保存的是上次启动时的旧UUID,两者无法匹配,导致people.first(where:)返回nil。

具体修复步骤

  1. 固定Person的ID值
    将people数组中的UUID改为固定值,避免每次启动生成新ID。示例修改如下:

    let people:[Person] = [
        Person(name: "Jack", age: 41, id: UUID(uuidString: "A0B1C2D3-E4F5-6789-ABCD-EF1234567890")!),
        Person(name: "Mary", age: 32, id: UUID(uuidString: "12345678-1234-5678-1234-567812345678")!),
        Person(name: "Linda", age: 18, id: UUID(uuidString: "98765432-1234-5678-1234-567812345678")!),
        Person(name: "Joe", age: 13, id: UUID(uuidString: "11112222-3333-4444-5555-666677778888")!),
        Person(name: "Kid", age: 1, id: UUID(uuidString: "99998888-7777-6666-5555-444433332222")!)
    ]
    

    这样每次启动APP,所有Person的ID保持一致,恢复窗口时保存的旧ID就能匹配到对应的Person。

  2. 确认状态恢复开关开启
    检查项目设置中的状态恢复选项:在项目的Info.plist中添加NSQuitAlwaysKeepsWindows键,设置值为YES,确保APP允许窗口状态恢复。

  3. 动态数据场景扩展
    如果需要使用动态生成的Person数据,需将数据持久化存储(比如用UserDefaults、CoreData或文件存储),确保重启后能加载到和上次相同ID的Person数据,而不是重新生成新数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 17:55:37