首页 > 解决方案 > 在环境中存储一个模拟对象

问题描述

在我的应用程序中,我想在 Environment 中存储一个对象以从各种视图执行网络查询。但是,在开发过程中,我想改用模拟,并从应用程序包中检索有效负载(JSON 格式)。这些是我采取的步骤:

  1. 指定协议
    typealias Token = String

    protocol MyAPIConforming {
        func signIn(username: String, password: String, completion: @escaping (Token?, Error?) -> Void)
    }
  1. 实现我需要的两个类
    class MockMyAPIManager: MyAPIConforming, ObservableObject {
        func signIn(username: String, password: String, completion: @escaping (Token?, Error?) -> Void) {
            // Read the JSON document from the app's bundle
        }
    }

    class MyAPIManager: MyAPIConforming, ObservableObject {
        func signIn(username: String, password: String, completion: @escaping (Token?, Error?) -> Void) {
            // Perform the network request
        }
    }
  1. 在环境中注入模拟对象
    let myManager = MockMyAPIManager()

    // Create the SwiftUI view that provides the window contents.
    let contentView = LoginView().environmentObject(myManager)
  1. 在视图中声明@Environment 对象
    struct LoginView: View {
    @EnvironmentObject var myManager: MyAPIConforming
    ...

我确实声明myManager了,MyAPIConforming因为我可以传递一个类型为MockMyAPIManageror的对象MyAPIManager

但是,在第 4 步中,我收到以下错误:

属性类型“MyAPIConforming”与其包装器类型“EnvironmentObject”的“wrappedValue”属性不匹配

我不确定该错误是否意味着无法保证采用 to 的对象MyAPIConforming也将采用该ObservableObject协议。

那么我需要做什么来存储MockMyAPIManager或存储MyAPIManager在环境中?这甚至可能吗?

标签: swiftuicombine

解决方案


这是一个可能的解决方案

struct LoginView<T: ObservableObject & MyAPIConforming>: View {
    @EnvironmentObject var myManager: T

        // other code here
}

更新:用法

用于内容视图

LoginView<MyAPIManager>().environmentObject(MyAPIManager())

并用于测试/预览

LoginView<MockMyAPIManager>().environmentObject(MockMyAPIManager())

推荐阅读