我应该在哪里在SwiftUI中为视图创建模型实例?

时间:2020-04-22 00:56:15

标签: mvvm swiftui

我是MVVM的新手。据我了解,我必须避免在视图结构中使用模型代码。

就我而言,我有2个视图,MainView和ChildView。 MainView没有ViewModel。但是ChildView具有ViewModel(例如ChildViewModel)。由于ChildViewModel仅在ChildView中使用,因此我没有在EnvironmentObject上注册模型实例,也没有将实例传递给MainView,因为MainView根本不使用模型。

我认为,最好的方法是ChildView自己创建自己的模型实例,如下所示。但我不确定是否可以。这是否违反了MVVM的规则?

struct ChildView: View {
    @ObservedObject var childViewModel = ChildViewModel()

    var body: some View { ... }
}

谢谢。

3 个答案:

答案 0 :(得分:1)

这是否违反了MVVM的规则?

不,不是,因为MVVM关于“责任分离”,并且提供的模式完全将View&ViewModel分开。此外,它也遵循“依赖注入”规则,因为您可以使用和

ChildView() // with default model

ChildView(childViewModel: ChildViewModel(...)) // some specific model

答案 1 :(得分:1)

我不同意接受的答案。我将提供自己的论据。

MVVM与拥有称为视图模型的对象无关。大多数MVVM开发人员只是为了拥有一个称为视图模型的对象而这样做。

因为MVVM关于“责任分离”

哪种设计模式与责任分离无关?

为什么您认为SwiftUI SDK设计不提供职责分离?

我必须避免在视图结构中使用模型代码

第一个视图结构不是视图,而是一个符合视图的模型。

例如struct Model: View

此设计旨在使您可以轻松地进行模型->视图绑定(以及可选的视图->模型绑定)。

有专门用于支持它的注解,例如@State@StateObject

例如在@State更改时重新渲染,编译器进行检查以防止从@State外部访问struct Model: View对象。

换句话说,struct Model: View是写模型代码的地方。通过设计!

请注意,它是struct Model,而不是class Model。 MVVM不考虑值类型。因此,MVVM不是利用值类型的不变性,而是认为在引用类型中使用单独的模型是个好主意吗?不是。

我再说一遍。 用于“责任分离”的REFERENCE类型的模型。

由于遗留原因,您必须创建一个单独的视图模型。这取决于绑定的设计方式。您需要一个单独的视图模型来绑定某种通用语言是完全可行的。

但是Swift不是一些通用语言。

我不知道为什么MVVM开发人员认为SwiftUI SDK创建者是白痴,对MVVM一无所知。事实是,SwiftUI具有如此高效的绑定设计,您不需要单独的视图模型来描述绑定。

甚至,我什至可以看到您现在具有从值类型模型(最具标志性的MVVM功能)进行绑定和自动更新视图的全部优势,而无需手动创建单独的视图模型。而且我不是MVVM开发人员。

SwiftUI默认创建视图模型。我曾多次尝试在其之上构建视图模型。他们都惨败了,因为现在视图模型已经很沉重了。

您不需要它,实际上您在使用它时会失去对SDK的支持。

或者这样想。 SwiftUI会删除UIViewController。

您看到MVC开发人员出来并坚持要创建一个单独的Controller对象吗?

适用相同的论点。例如;

因为MVC是关于“责任分离”的,并且提供了模式 与View&Control完全分开。而且它遵循“依赖性 注射”规则

不要让这些抽象的词使您感到困惑。有适用于所有事物的基本原则。

对于您的问题,这是MVVM的一种无效形式。 ChildView应该是您的模型。 而且这些MVVM比这些MVVM开发人员告诉您的要多。

例如;

struct ChildView: View {
    @State var value: Value 
    @StateObject var resource: JSON
    var body: some View { ... }
}

答案 2 :(得分:0)

这不违反MVVM模式。如果您的主视图需要将某些参数传递给子视图,则应使用init参数。但是,需要注意的一件事是,每当您从主视图导航到子视图时,都会创建ChilViewModel的新实例。在不可接受的用例中,每次用户导航到子视图时,都会在父视图中创建视图模型并将其传递给子视图以维护相同的实例。两者都没有违反MVVM模式。希望这能回答你的问题。