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

如何在App关闭后保存自定义结构体数据?@AppStorage使用遇阻

存储自定义结构体数组的最佳方案

为什么@AppStorage无法直接使用

@AppStorage仅支持符合RawRepresentable的基础类型(如String、Int、Bool等),你的[ToDoTasks]是自定义结构体数组,无法直接被@AppStorage处理,这就是你之前尝试失败的原因。

推荐方案:UserDefaults + Codable + ObservableObject

因为你的ToDoTasks已经实现了Codable协议,我们可以将数组编码为Data后存入UserDefaults,读取时再解码回数组。结合ObservableObject可以更优雅地管理数据的读写逻辑:

步骤1:创建ViewModel管理数据

class ToDoViewModel: ObservableObject {
    @Published var items: [ToDoTasks] = []
    
    private let storageKey = "SavedToDoTasks"
    
    init() {
        loadSavedTasks()
    }
    
    // 从UserDefaults读取数据
    private func loadSavedTasks() {
        guard let savedData = UserDefaults.standard.data(forKey: storageKey) else {
            // 无保存数据时使用默认值
            items = [ToDoTasks(task: "Test", date: Date())]
            return
        }
        
        do {
            items = try JSONDecoder().decode([ToDoTasks].self, from: savedData)
        } catch {
            print("数据解码失败:\(error.localizedDescription)")
            items = [ToDoTasks(task: "Test", date: Date())]
        }
    }
    
    // 将数据保存到UserDefaults
    func saveTasks() {
        do {
            let encodedData = try JSONEncoder().encode(items)
            UserDefaults.standard.set(encodedData, forKey: storageKey)
        } catch {
            print("数据编码失败:\(error.localizedDescription)")
        }
    }
}

步骤2:在View中使用ViewModel

struct ContentView: View {
    // 使用@StateObject初始化ViewModel,确保生命周期与View一致
    @StateObject private var viewModel = ToDoViewModel()
    
    var body: some View {
        VStack {
            // 示例:展示任务列表
            List(viewModel.items) { task in
                VStack(alignment: .leading) {
                    Text(task.task)
                    Text(task.date.formatted())
                        .font(.caption)
                        .foregroundColor(.gray)
                }
            }
            
            // 示例:添加新任务
            Button("添加任务") {
                viewModel.items.append(ToDoTasks(task: "新任务", date: Date()))
                viewModel.saveTasks()
            }
        }
        // 可选:监听items变化自动保存,无需手动调用saveTasks
        .onChange(of: viewModel.items) { _ in
            viewModel.saveTasks()
        }
    }
}

替代方案:Core Data(适合复杂场景)

如果你的待办任务数量较多,或者需要支持复杂查询、关联数据等操作,Core Data会是更合适的选择。它提供了更强大的数据持久化能力,但学习成本比UserDefaults高一些。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 10:50:55