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

SwiftUI提醒应用结合ViewModel实现数据持久化问题排查

问题根因
  • 核心问题是Swift的数组为值类型,你在初始化HomeViewModel时传入store.reminds属于值传递,会生成一份独立的数组副本:后续ViewModel内部新增提醒修改的是自己持有的副本,ReminderStore里的数组始终没有更新;同时App启动后异步加载完本地数据赋值给store.reminds时,ViewModel持有的副本还是初始化时的空值,两边数据完全不同步,所以持久化时保存的是Store里的旧数据,重启后自然看不到新增内容。
  • 你尝试加$前缀传绑定报错的原因是:$store.reminds生成的是SwiftUI专属的Binding<[Reminder]>类型,但你的HomeViewModel构造函数参数定义为普通的[Reminder]数组类型,类型不匹配导致编译失败。且ViewModel作为逻辑层,不应该依赖视图层的Binding类型,会破坏分层设计。
最小改动修复方案

保持现有ViewModel架构不变,统一数据源为ReminderStore,消除多副本数据不同步问题,不需要引入Binding类型:

1. 修改HomeViewModel代码

不再独立持有提醒数组副本,改为持有ReminderStore实例,直接操作Store内的统一数据源:

import Foundation

class HomeViewModel: ObservableObject {
    private let store: ReminderStore
    @Published var newRemindData = Reminder.Data()

    // 直接读写Store内的reminds数组,保证数据源唯一
    var reminds: [Reminder] {
        get { store.reminds }
        set { store.reminds = newValue }
    }

    // 构造函数改为接收ReminderStore实例
    init(store: ReminderStore) {
        self.store = store
    }

    func addRemindData(remindData: Reminder.Data) {
        let newRemind = Reminder(data: remindData)
        reminds.append(newRemind)
        newRemindData = Reminder.Data()
    }
}

2. 修改RemindersApp根视图代码

初始化HomeViewModel时传入store实例,而非数组值:

import SwiftUI

@main
struct RemindersApp: App {
    @StateObject private var store = ReminderStore()

    var body: some Scene {
        WindowGroup {
            NavigationView {
                HomeView(homeVM: HomeViewModel(store: store)) {
                    ReminderStore.save(reminds: store.reminds) { result in
                        if case .failure(let error) = result {
                            fatalError(error.localizedDescription)
                        }
                    }
                }
                .navigationBarHidden(true)
            }
            .onAppear {
                ReminderStore.load { result in
                    switch result {
                    case .failure(let error):
                        fatalError(error.localizedDescription)
                    case .success(let reminds):
                        store.reminds = reminds
                    }
                }
            }
        }
    }
}

3. 修改Preview预览代码

适配新的构造函数:

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        let testStore = ReminderStore()
        testStore.reminds = Reminder.sampleReminders
        return HomeView(homeVM: HomeViewModel(store: testStore), saveAction: {})
    }
}

修复后逻辑说明
  • 全项目只有ReminderStore内一份提醒数据源,不存在多副本不同步问题
  • App启动加载本地数据完成后,ViewModel读取到的自动是最新的加载结果
  • 用户新增提醒时,ViewModel直接修改Store内的数组,触发保存时拿到的是全量最新数据
  • 逻辑层不依赖SwiftUI的Binding类型,符合原有ViewModel架构的分层设计

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 07:30:52