SwiftUI 在哪里加载 MVVM 中的数据

Posted

技术标签:

【中文标题】SwiftUI 在哪里加载 MVVM 中的数据【英文标题】:SwiftUI where to load data in MVVM 【发布时间】:2020-05-10 22:54:31 【问题描述】:

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

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

我应该在 Service 中的其他地方为 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
        
     

【问题讨论】:

【参考方案1】:

使用专用网络服务。

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

问题是,它与您认为您对 MVVM 了解的所有内容背道而驰。

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

其背后的想法是重构视图绑定模型和相关的逻辑/效果。

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

随着时间的推移,开发者开始认为 ViewModel 是理所当然的,既然它是 android 的规范,它必须在 ios 中工作,对吧?

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

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

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

任何符合 ObservableObject 的人都可以被观察到(触发视图更新),这样 超出了视图模型的狭义定义(视图相关的属性)。可观察对象 可以是服务共享资源。例如。;网络服务。恭喜你 刚刚迈出了进入更大世界的第一步。

我为什么要引入引用类型视图模型来扩充值类型模型视图 在围绕值类型构建的 SDK 中符合 View 的每个此类值类型?斯威夫特不是 爪哇?

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

    创建一个专用的网络服务,例如;

    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 */
        
    
    

    使用它,例如;

    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**
          
      
    

    完成。

    为什么我们又需要 ViewModel? 请在 cmets 中告诉我。

【讨论】:

我很感兴趣,但是你有一个完整的工作代码示例吗?我已经阅读了您的几篇文章,但我很难看到它们在实践中是如何结合在一起的。【参考方案2】:

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

仅用于此视图的数据

ViewModel 获取数据没问题。以repo 为例。

请注意,存储在 ObservableObject 中的数据不会持久保存。因此,您必须将ViewModel 作为@State 存储在父视图中。看here。

要为整个应用持久化的数据

然后我建议使用.environmentObject() 将某种“存储”加载到您的视图中。以repo 为例。

【讨论】:

以上是关于SwiftUI 在哪里加载 MVVM 中的数据的主要内容,如果未能解决你的问题,请参考以下文章

在 SwiftUI MVVM 中的子视图和父视图之间共享值

我如何(或应该?)用嵌套的 managedObjectContext 替换这个 CoreData SwiftUI 应用程序中的 MVVM?

SwiftUI - MVVM之ViewModel

SwiftUI-MVVM

SwiftUI MVVM:父视图更新时重新初始化子视图模型

SwiftUI 和 MVVM:当视图模型更改“数据源”(`@Publish items`)本身时,如何为“列表元素更改”设置动画