SwiftUI 和 MVVM 设计模式

Mic*_*ael 3 design-patterns mvvm ios swift swiftui

我试图弄清楚如何使用 MVVM 设计模式和 SwiftUI 来实现以下目标。

\n

我只想拥有网络操作队列的 1 个实例(使用OperationQueue),其中任何视图模型都需要发送任何网络请求,但我听说创建单例不是首选,我应该将网络队列对象传递到它所在的位置需要。

\n

因此,如果我在场景委托中创建网络操作队列的实例,并将它们传递到 ContentView 初始化程序中,并将其存储在那里的对象中,然后传递到随后创建的视图中。

\n

这似乎不是一个好的 MVVM 设计实践,因为根据我的理解,视图应该只拥有 ViewModel?

\n

实现这一目标的最佳方法是什么?

\n

编辑:对此进行更多思考,我可以通过其构造函数将其传递到视图中,然后在构造函数中我可以创建视图模型并直接传递它,以便视图不拥有任何东西。

\n

但我仍然需要一个单例,那么如何将单例作为依赖注入传递而不是全局使用它呢?

\n

rfa*_*ias 5

我们不应该创建单例,因为它是获取全局变量的简单方法,但这并不意味着我们永远不应该使用它们。

\n\n

就您而言,如果我理解正确的话,您基本上是在创建一个可供整个应用程序使用的服务。您可以 A) 创建一个具有您需要的网络功能的可重用类(并在您需要的任何地方实例化),或者 B) 创建一个包含单例实例的类,可以在任何地方轻松访问该类。

\n\n

例如,如果您需要保持所有调用者共有的某些状态,或者需要维护等待队列,那么单例将是更好的选择。

\n\n

选项A

\n\n
class NetworkService {\n\n    init() {\n        // init\n    }\n\n    // Your properties and methods\n    func someFunction() {}\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

在 ViewModel 中的用法:

\n\n
let networkService = NetworkService()\nnetworkService.someFunction()\n
Run Code Online (Sandbox Code Playgroud)\n\n

选项B

\n\n
class NetworkService {\n    static let shared = NetworkService()\n    private let queue : Any?\n\n    // Your properties and methods\n    func someFunction() {}\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

用法:

\n\n
NetworkService.shared.someFunction()\n
Run Code Online (Sandbox Code Playgroud)\n\n

不管怎样,这仍然是 MVVM。数据不与任何特定视图相关,也不与特定模型相关;它只是一个您可以在任何需要它的 ViewModel 中调用的服务。

\n

  • 因为视图模型会在单元测试中尝试调用单例。这意味着进行真正的网络调用。您想要的是将网络服务作为协议注入。因此,为网络服务创建一个协议,并将网络服务的实例注入到视图模型 init 中。在单元测试中,您创建一个遵循相同协议的 MockNetworkService 并注入该协议。您的模拟当然不会进行真正的网络调用。这就是松耦合和依赖注入的基本原理。 (4认同)