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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 10:27:26