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
相关产品推荐
相关产品推荐

