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

SwiftUI:如何将一个ObservableObject的Published变量嵌入另一个?

嘿,这个问题提得很到位!确实有比手动订阅sink更简洁的方式来同步Auth的状态到你的SampleViewModel里,不用写那些繁琐的订阅代码,下面给你介绍几种实用方案:

方案1:直接通过计算属性访问单例状态

你完全不需要在SampleViewModel里维护自己的authState变量,直接通过计算属性引用Auth.shared的状态就行。因为SwiftUI会自动追踪ObservableObject的@Published属性变化,哪怕是通过单例访问的:

class SampleViewModel: ObservableObject {
    // 用计算属性直接返回单例的状态,不用自己存副本
    var authState: Auth.AuthState {
        Auth.shared.currentState
    }
}

使用场景:如果你的ViewModel只需要读取Auth状态,不需要基于这个状态做额外的本地逻辑处理,这种方式最省事。甚至在SwiftUI视图里,你可以直接观察Auth.shared,连ViewModel的这个属性都省了:

struct SampleView: View {
    @ObservedObject private var auth = Auth.shared
    
    var body: some View {
        switch auth.currentState {
        case .notAuthenticated:
            Text("请先登录")
        case .authenticated:
            Text("欢迎回来!")
        }
    }
}

方案2:将Auth单例作为ViewModel的@ObservedObject

如果你的ViewModel需要基于Auth状态做一些业务逻辑(比如根据登录状态加载不同数据),可以把Auth.shared作为ViewModel的@ObservedObject,这样ViewModel会自动感知到Auth状态的变化,无需手动订阅:

class SampleViewModel: ObservableObject {
    // 把Auth单例作为ObservedObject,自动追踪它的Published属性变化
    @ObservedObject private var auth = Auth.shared
    
    // 同样可以用计算属性简化访问
    var authState: Auth.AuthState {
        auth.currentState
    }
    
    // 示例:根据Auth状态加载数据
    func loadData() {
        if authState == .authenticated {
            // 加载已登录用户的数据
        } else {
            // 加载游客数据
        }
    }
}

这样当Auth的currentState变化时,@ObservedObject会自动触发ViewModel的objectWillChange通知,订阅这个ViewModel的视图也会随之更新,完全不用手动写sink或者管理订阅的生命周期。

补充:原来的写法有个隐藏坑

你之前用sink的方式其实存在一个问题:订阅没有被存储,会在init结束后立即取消!因为sink返回的AnyCancellable如果不被保留,会被销毁,订阅就失效了。哪怕你想保留那个写法,也需要把订阅存在ViewModel的一个Set<AnyCancellable>里:

class SampleViewModel: ObservableObject {
    @Published var authState = Auth.shared.currentState
    private var cancellables = Set<AnyCancellable>()
    
    init() {
        Auth.shared.$currentState
            .assign(to: \.authState, on: self)
            .store(in: &cancellables)
    }
}

但显然上面两种方案比这个要简洁得多,也更符合SwiftUI的响应式设计理念。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 14:42:36