You need to enable JavaScript to run this app. SwiftUI使用@ObservedObject ViewModel时如何绑定状态更新视图
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI使用@ObservedObject ViewModel时如何绑定状态更新视图

问题根源

你的ViewModel虽然声明遵循ObservableObject协议,但所有需要驱动视图刷新的状态属性都没有添加@Published修饰符。
ObservableObject本身仅提供默认的objectWillChange发布器,只有被@Published标记的属性发生变更时,才会自动触发该发布器,向所有绑定的视图发送更新通知;未被标记的普通属性修改完全不会触发任何事件,因此视图不会像之前使用@State时那样自动刷新。

修复方案

直接给ViewModel中负责驱动视图状态切换的三个属性添加@Published修饰符即可,修改后的完整ViewModel代码如下:

final class ContentViewModel: ObservableObject {

    // 为视图状态属性添加@Published修饰
    @Published var movies: [Movie] = []
    @Published var isLoading: Bool = false
    @Published var fetchError: String?
    
    private let dataLoader: DataLoaderProtocol
    
    init(dataLoader: DataLoaderProtocol = DataLoader()) {
        self.dataLoader = dataLoader
        fetch()
    }

    func fetch() {
        isLoading = true
        dataLoader.loadMovies { [weak self] result, error in
            guard let self = self else { return }
            // 网络回调通常在后台线程,切回主线程再修改状态,避免UI更新异常
            DispatchQueue.main.async {
                self.isLoading = false
                guard let result = result else {
                    return print("api error fetching")
                }
                guard let error = result.errorMessage, error != "" else {
                    self.movies = result.items
                    return
                }
                self.fetchError = error
            }
        }
    }
}
注意事项
  • 添加@Published后,三个属性的任何变更都会自动触发objectWillChange信号,被@ObservedObject修饰的视图收到信号后会重新计算body,完全复刻之前@State驱动的动态视图切换效果。
  • 补全的主线程切换是常见隐藏踩坑点:绝大多数网络请求回调运行在后台线程,即使加了@Published,在后台线程修改视图相关状态也可能出现UI更新延迟、无响应的问题,切回主线程修改是SwiftUI下的标准实践。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.31 00:15:04