SwiftUI 在 MVVM 中加载数据的位置

SwiftUI where to load data in MVVM

我有一个名为 Requests 的视图,它有一个名为 RequestViewModel 的视图模型。此视图模型将类型为 Request 的模型作为参数,然后它为视图提供了几种方法。问题是我需要先从 firebase 加载这些 requests 但我不知道在哪里。

视图模型是获取数据的好地方吗,因为我觉得它不是?对于其他视图模型,我也有类似的情况;对于前 PackageViewModel 和更多...

我应该在服务中为 ex 将此数据加载到其他地方,然后将其传递给此视图模型,还是有其他方法可以做到这一点?

class RequestViewModel: ObservableObject {
    @Published var request: Request
    @Published var requests: [Request] = []

    init(request: Request) {
        self.request = request
    }

    func loadRequests() -> Void {
        network call here {
            self.requests = requests
        }
    } 
}

这真的取决于。您是否仅将数据用于这一个视图?或者您是否在整个应用程序中使用它?

仅用于此视图的数据

ViewModel 获取数据没问题。查看此 repo 示例。

Be aware that data stored an ObservableObject doesn't persist. So you'd have to store the ViewModel as a @State in the parent view. Look .

要为整个应用保留的数据

然后我建议使用 .environmentObject() 将某种“商店”加载到您的视图中。查看此 repo 作为示例。

使用专用网络服务。

搜索你的感受,你知道它是真实的。

问题是,它与您自认为了解的有关 MVVM 的所有知识背道而驰。

大多数 MVVM 开发人员使用视图模型作为网络请求(有副作用)、业务逻辑和视图控件的便捷包装器。

其背后的想法是重构视图绑定模型和关联 logic/effects。

与所有设计模式一样,一些开发人员会滥用它、扭曲它、从 java 复制并粘贴它......等等

随着时间的推移,开发人员开始认为 ViewModel 是理所当然的,因为它在 Android 中是一种规范,它必须在 iOS 中工作,对吧?

任何称职的开发人员在尝试将 MVVM 移植到 SwiftUI 时都会问这些问题:

  • SwiftUI有绑定机制吗?它是如何工作的?

  • struct Model: View {...},这是模型-视图映射吗?如果是这样,我可能不需要申报 一个单独的视图模型? (专业问题)

  • 谁符合ObservableObject,谁就可以被观察到(触发视图更新),这样下去 超出视图模型的狭义定义(与视图相关的属性)。可观察对象 可以是 服务 共享资源 。例如。;一种网络服务。恭喜你 刚刚迈出迈向更大世界的第一步。

  • 为什么我要引入引用类型视图模型来扩充值类型模型视图 每个这样的值类型都符合围绕值类型构建的 SDK 中的视图? Swift 不是 java?

现在我们有足够的设置来正确回答您的问题。

  1. 创建专用网络服务,例如;

    final class Resource: ObservableObject { // don't even need inheritance, OOP isn't always the best solution in all situations 
        @Published var requests = [Requests]()
        // publish other resources
        func loadRequests() {
            /* update requests in callback */
        }
    }
    
  2. 使用它,例如;

    struct Model: View {
        @State var model = MyModel() // can be "view model", because it maps to view 
        @EnvironmentObject var res: Resource
        // or as an alternative, @ObservedObject var res = Resource()
        var body: some View {
            // access the automatic binding provided by SwiftUI, e.g.; res.requests
            // call res.loadRequests() to mutate internal state of a reference type
            // note that stateful part of the "view model" is refactored out 
            // so that `model` can be value type, yet it provides binding via @State
            // instead of ObservableObject, which has to be reference type
            // this is the brilliance of SwiftUI, it moves heaven and earth so you have 
            // the safety of immutability from value type, **unlike MVVM**
        }  
    }  
    
  3. 完成。

  4. 为什么我们又需要 ViewModel? 请在评论中告诉我。