SwiftUI中如何绑定两个ObservableObject对象?
实现DataManager与ViewModel的属性双向绑定
你尝试用@Binding直接绑定两个ObservableObject的属性是行不通的——@Binding的设计场景是视图间的状态传递,它需要接收一个Binding类型的值,而dataManager.$stuff是Published.Publisher类型,两者类型不兼容。下面提供两种可行的实现方案:
方案一:Combine双向订阅同步
利用Combine框架的订阅机制,实现DataManager和ViewModel属性的双向同步:
import Combine class ViewModel: ObservableObject { @Published var mirroredStuff: [String] = [] private var cancellables = Set<AnyCancellable>() init(dataManager: DataManager) { // 同步DataManager的stuff变化到ViewModel的mirroredStuff dataManager.$stuff .assign(to: \.mirroredStuff, on: self) .store(in: &cancellables) // 同步ViewModel的mirroredStuff变化回DataManager的stuff $mirroredStuff .assign(to: \.stuff, on: dataManager) .store(in: &cancellables) } } class DataManager: ObservableObject { @Published var stuff: [String] = [] func fetchStuff() { DispatchQueue.main.asyncAfter(deadline: .now() + 2) { self.stuff = ["One", "Two", "Three"] } } }
- 用
assign(to:on:)方法将Publisher的输出赋值给目标属性,实现单向同步 - 双向同步需要同时订阅两个对象的属性变化,并互相赋值
cancellables集合用于管理订阅生命周期,避免内存泄漏
方案二:计算属性+事件转发
让ViewModel持有DataManager实例,通过计算属性直接读写DataManager的属性,同时转发DataManager的变更事件:
import Combine class ViewModel: ObservableObject { private let dataManager: DataManager private var cancellables = Set<AnyCancellable>() var mirroredStuff: [String] { get { dataManager.stuff } set { dataManager.stuff = newValue } } init(dataManager: DataManager) { self.dataManager = dataManager // 监听DataManager的变更事件,触发ViewModel的objectWillChange dataManager.objectWillChange .sink { [weak self] _ in self?.objectWillChange.send() } .store(in: &cancellables) } } class DataManager: ObservableObject { @Published var stuff: [String] = [] func fetchStuff() { DispatchQueue.main.asyncAfter(deadline: .now() + 2) { self.stuff = ["One", "Two", "Three"] } } }
- 计算属性
mirroredStuff直接代理DataManager的stuff属性,读写操作都会作用到DataManager上 - 监听DataManager的
objectWillChange事件,当DataManager内部数据变化时,手动发送ViewModel的objectWillChange,确保视图能感知到数据更新
内容的提问来源于stack exchange,提问作者Randall
相关产品推荐
相关产品推荐

