SwiftUI中如何让ViewModel监听单例DataManager的@Published属性变化?
修复SwiftUI中DataManager单例变更无法触发View更新的问题
当前代码的核心问题是:ViewModel的displayModels计算属性依赖DataManager的modelsA,但ViewModel没有监听DataManager的@Published属性变化。当modelsA(或modelsB)更新时,ViewModel不会发送自身的objectWillChange通知,导致View无法感知到displayModels的变化。
以下是两种可行的修复方案:
方法一:使用Combine订阅DataManager的特定属性变化
通过Combine框架监听DataManager目标属性的变更,手动触发ViewModel的更新通知,精准控制View的刷新时机。
修改后的ViewModel代码:
import Combine class ViewModel: ObservableObject { @Published var someState: Bool = false private let dataManager = DataManager.shared private var cancellables = Set<AnyCancellable>() var displayModels: [DisplayModel] { dataManager.modelsA.compactMap { MapModelAToDisplayModel($0) } } init() { // 监听modelsA的变化,触发ViewModel更新 dataManager.$modelsA .sink { [weak self] _ in self?.objectWillChange.send() } .store(in: &cancellables) // 若需监听modelsB,添加以下代码 // dataManager.$modelsB // .sink { [weak self] _ in // self?.objectWillChange.send() // } // .store(in: &cancellables) } }
方法二:将DataManager声明为ViewModel的@ObservedObject
把DataManager作为ViewModel的@ObservedObject属性,自动监听其所有@Published属性的变化,简化代码逻辑。
修改后的ViewModel代码:
class ViewModel: ObservableObject { @Published var someState: Bool = false @ObservedObject private var dataManager = DataManager.shared var displayModels: [DisplayModel] { dataManager.modelsA.compactMap { MapModelAToDisplayModel($0) } } }
方案特点对比
- 方法一:更灵活,可针对单个属性监听,避免无关变更触发的不必要刷新;
- 方法二:更简洁,自动监听DataManager所有
@Published属性的变化,适合需要同步所有数据更新的场景。
内容的提问来源于stack exchange,提问作者Mev
相关产品推荐
相关产品推荐

