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

如何让@propertyWrapper注入的LocalDataManager成为@ObservableObject?

改造方案

核心思路是在不改动原有依赖注入测试逻辑的前提下,通过ObservableObject协议桥接属性变更事件,具体实现步骤如下:

1. 调整LocalDataManagerProtocol协议,限定为类类型

// 仅添加AnyObject限定,原有属性定义不变
protocol LocalDataManagerProtocol: AnyObject {
    var isSignedIn: Bool { get set }
}

2. 改造LocalDataManager遵守ObservableObject,桥接@UserDefault的变更事件

import Combine
import Foundation

final class LocalDataManager: ObservableObject, LocalDataManagerProtocol {
    @UserDefault(key: .isSignedIn, defaultValue: false)
    var isSignedIn: Bool
    
    private var cancellables = Set<AnyCancellable>()
    
    init() {
        // 把UserDefault的发布事件和当前类的objectWillChange绑定
        $isSignedIn
            .receive(on: DispatchQueue.main)
            .sink { [weak self] _ in
                self?.objectWillChange.send()
            }
            .store(in: &cancellables)
    }
}

// 单元测试用的Mock类也遵守ObservableObject即可
final class LocalDataManagerMock: ObservableObject, LocalDataManagerProtocol {
    var isSignedIn: Bool = false
    // 测试时如果需要模拟属性变更,也可以按需求加@Published或者手动触发objectWillChange
}

3. 改造视图模型,监听注入的localDataManager的变更事件

import Combine

class DataViewModel: ObservableObject {
    @Injection(\.localDataManager) var localDataManager
    private var cancellables = Set<AnyCancellable>()
    
    init() {
        // 把注入的localDataManager的变更事件和当前视图模型的objectWillChange绑定
        if let observableManager = localDataManager as? any ObservableObject {
            observableManager.objectWillChange
                .receive(on: DispatchQueue.main)
                .sink { [weak self] _ in
                    self?.objectWillChange.send()
                }
                .store(in: &cancellables)
        }
    }
}

效果说明

原有依赖注入的测试逻辑完全不受影响,单元测试时仍可以直接通过InjectedDependency[\.localDataManager] = LocalDataManagerMock()替换实现。当isSignedIn属性变更时,事件会沿着@UserDefault -> LocalDataManager.objectWillChange -> DataViewModel.objectWillChange传递,触发SwiftUI视图自动刷新。

可选优化(iOS 17+)

如果你的项目最低部署版本是iOS 17,可以直接使用Swift Observation框架替代Combine方案,代码更简洁:

  1. 给LocalDataManager和LocalDataManagerMock加上@Observable宏,不需要再手动处理发布者
  2. 视图模型不需要添加任何监听代码,SwiftUI会自动跟踪@Observable类的属性变更
  3. 原有依赖注入逻辑完全不变

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 02:39:03