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

SwiftUI中Presenter的viewModel用@Published还是@ObservedObject?为什么

SwiftUI属性包装器场景使用判断

结论

你给出的两种写法在当前普通Presenter类的场景下均不正确,两个属性包装器的适用场景都和当前使用位置不匹配。

各写法错误原因

  • 关于@ObservedObject private(set) var viewModel: ContentViewModel
    @ObservedObject是SwiftUI框架专门为符合View协议的结构体设计的属性包装器,作用是让视图层可以监听ObservableObject对象的变更,自动触发视图重绘。它只能在View内部使用,放在普通业务类中完全不会生效,也没有对应作用,编译器还会抛出无效使用的警告。

  • 关于@Published private(set) var viewModel: ContentViewModel
    @Published是专门给遵守ObservableObject协议的类的内部属性使用的属性包装器。它的作用是当被修饰的属性值发生变化时,自动调用所属类的objectWillChange发送变更通知。如果你的Presenter本身没有遵守ObservableObject协议,添加@Published修饰不会产生任何预期效果。

正确实现方案

如果你需要在Presenter类中持有并监听ContentViewModel的变更,直接声明属性手动订阅变更即可,示例如下:

import Combine

class Presenter {
    private(set) var viewModel: ContentViewModel
    // 存储订阅令牌
    private var cancellables = Set<AnyCancellable>()

    init(viewModel: ContentViewModel) {
        self.viewModel = viewModel
        // 手动订阅viewModel的变更事件
        viewModel.objectWillChange
            .sink(receiveValue: { [weak self] _ in
                // 此处处理viewModel变化后的业务逻辑
            })
            .store(in: &cancellables)
    }
}

如果你的Presenter本身是需要给SwiftUI视图监听的业务层对象,那让Presenter遵守ObservableObject协议即可,此时如果要把viewModel的变更同步给外部视图,也可以在订阅时手动发送Presenter自己的变更通知:

import Combine

class Presenter: ObservableObject {
    private(set) var viewModel: ContentViewModel
    private var cancellables = Set<AnyCancellable>()

    init(viewModel: ContentViewModel) {
        self.viewModel = viewModel
        // 把viewModel的变更转发为Presenter自身的变更,供外部View监听
        viewModel.objectWillChange
            .sink(receiveValue: { [weak self] _ in
                self?.objectWillChange.send()
            })
            .store(in: &cancellables)
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 04:36:02