当我需要从两个不同的 Web 服务获取控制器数据时,我应该如何使用 MVVM 和依赖注入?

How should I use MVVM and Dependency Injection when I need to fetch a controller data from two different web services?

我在我的 swift 项目中使用 MVVM 设计模式。在视图控制器中,我需要从两个不同的 Web 服务获取数据。所以我需要在控制器中创建一个视图模型,如下所示:

class MyViewController: UIViewController {

var viewModel: MyViewModel = MyViewModel(repository: NetworkLayer(service1: WebService1(), service2: WebService2()))

    override func viewDidLoad() {
         super.viewDidLoad()
         viewModel.getData(catUrl, categoryId: "\(catId)")
    }
} 

视图模型负责从服务器获取数据并通过控制器更新视图。我找到了存储库设计模式和依赖注入来解决我的问题:

class MyViewModel {
    var webService1: WebService1?
    var webService2: WebService2?

    init(repository: NetworkLayer) {
        self.webService1 = repository.service1
        self.webService2 = repository.service2
    }

    func getData(_ url: String, categoryId: String) {
        webService1?.delegate = self
        webService1?.getData(urlCode: url)

        webService2?.delegate = self
        webService2?.getProducts(queryString: "sortby=14&pageno=0&status=2&pagesize=20&category=c\(categoryId)")
    }
}

class NetworkLayer: WebService1Delegate, WebService2Delegate {  
    var webService1: WebService1?
    var webService2: WebService2?

    init(service1: WebService1, service2: WebService2) {
        self.service1 = service1
        self.service2 = service2
    }
}

谁能告诉我我处理这种情况的方法是否正确?如果没有,最好的应对方式是什么?

如果您想正确实施存储库模式,我建议您应该使用协议。例如,您将创建这样的协议

protocol RepositoryProtocol {
    func fetchInformation() -> String
}

因此您的服务 classes 必须实现这一点。所以这是一个例子

class MyService: RepositoryProtocol {
    func fetchInformation() -> String {

        return ""
    }
}

为了安全起见,您还应该创建一个视图模型协议。

protocol ViewModel {
    associatedtype Repo
    init (withRepo repo: Repo)
}

所以这就是说,class符合此 ViewModel 协议的 es 将在视图模型中定义一些类型,并且必须将其注入到 init 方法中。还有好处,它不再是可选对象。

下面是视图模型的示例

struct MyViewModel : ViewModel {
    typealias Repo = RepositoryProtocol

    let repo : RepositoryProtocol
    init(withRepo repo: Repo) {
        self.repo = repo
    }
}

所以在这里你可以看到,你的视图模型必须注入一个符合你在视图模型中定义的协议的对象class。如您所见,typealias 已用于表示此对象将属于 RepositoryProtocol 类型。您可以更新视图模型协议,以便它要求视图模型使用您需要的尽可能多的服务进行初始化

这是处理回购模式和依赖项注入的更好方法。