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

SwiftUI父视图模型对象数组更新问题:切换标签页后状态丢失

问题分析与解决方案

问题根源

  1. 值类型拷贝导致数据不一致:[UserField]是值类型,TabBarViewModel的userFields是account.userFields的拷贝,修改ViewModel的数组不会同步到Account的原始数组。
  2. DataViewModel重置数据:切换标签页时,DataViewModel的fetchData()方法会将绑定的userFields重新赋值为Account的原始数组,覆盖修改后的内容。
  3. Account数据源未同步更新:Account的userFields作为lazy加载的初始数据,修改ViewModel的数组后并未同步更新这里的原始数据。

解决方案

1. 移除DataViewModel中重置数据的逻辑

删除fetchData()方法,或确保该方法仅在应用首次启动时调用,避免切换标签页时覆盖已修改的数据:

extension DataScene {
    class DataViewModel: ObservableObject {
        @Binding var userFields: [UserField]
        init(_ userFields: Binding<[UserField]>) {
            _userFields = userFields
        }
        // 移除fetchData(),或仅在初始化时调用一次
    }
}

2. 同步Account与ViewModel的数据

在修改内存数组的同时,同步更新Account的userFields,确保所有数据源保持一致:

extension FieldForm {
    class FieldViewModel: ObservableObject {
        @Binding var userFields: [UserField]
        let account: Account // 需要传入Account引用
        
        init(muserFields: Binding<[UserField]>, account: Account) {
            self._userFields = userFields
            self.account = account
        }
        
        func deleteTapped() {
            guard let name else { return }
            let record = userFields.filter { $0.id == account.id && $0.name == name }.first
            record?.delete() // 同步到SQLite
            if let record {
                // 更新绑定的数组
                userFields.removeAll { $0.id == record.id && $0.name == record.name }
                // 同步更新Account的数组
                account.userFields.removeAll { $0.id == record.id && $0.name == record.name }
            }
        }
    }
}

3. 统一数据源管理

将Account改为ObservableObject,用@Published包装userFields,确保数据变化能通知到所有关联视图:

class Account: ObservableObject {
    @Published var userFields: [UserField]
    
    init() {
        // 首次加载数据,替代lazy var逻辑
        userFields = UserField.fetchAll()
    }
}

然后让TabBarViewModel直接关联Account的数据源,避免不必要的拷贝:

extension TabBarScene {
    class TabBarViewModel: ObservableObject {
        let account: Account
        @Published var userFields: [UserField] {
            didSet {
                // 同步回Account的数据源
                account.userFields = userFields
            }
        }
        
        init(sessionService: SessionService) {
            self.account = sessionService.account
            self.userFields = account.userFields
        }
    }
}

4. 统一绑定到单一数据源

所有子视图(DataScene、FieldForm)都通过绑定获取TabBarViewModel的userFields,确保所有修改都指向同一个数据源,切换标签页时不会丢失状态。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 19:14:55