将模拟对象存储在环境中

时间:2020-06-03 03:08:51

标签: swiftui combine

在我的应用程序中,我想在环境中存储对象以从各种视图执行网络查询。但是,在开发过程中,我想改用模拟,然后从应用程序的捆绑包中检索有效负载(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
    ...

我确实声明myManagerMyAPIConforming,因为我可能会传递类型为MockMyAPIManagerMyAPIManager的对象。

但是,在第4步中,出现以下错误:

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

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

那么我需要怎么做才能在环境中存储MockMyAPIManagerMyAPIManager?这有可能吗?

1 个答案:

答案 0 :(得分:1)

这是一个可能的解决方案

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

        // other code here
}

更新:用法

用于内容查看

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

并用于测试/预览

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