简体   繁体   English

SwiftUI 2 View Models in a View

[英]SwiftUI 2 View Models in a View

I have this view which takes as a param its own View Model.我有这个观点,它以自己的观点 Model 作为参数。 Inside this view I need to show another view which in order for it to be displayed, needs its own View Model.在这个视图中,我需要显示另一个视图,为了显示它,需要它自己的视图 Model。 So I present the Purchase view and then inside the Purchase view I need to display the details of the actual item which was purchased.所以我展示了Purchase视图,然后在Purchase视图中我需要显示购买的实际项目的详细信息。 So I pass as a parameter also the ItemViewModel .所以我也将ItemViewModel作为参数传递。 Both PurchaseViewModel and ItemViewModel are used on other views also. PurchaseViewModelItemViewModel也用于其他视图。

It could happen in the feature that I would also need ClientViewModel which would be used to display data about the actual buyer of this item.它可能发生在我还需要ClientViewModel的功能中,该模型将用于显示有关该商品的实际买家的数据。 Does this mean that I would need to pass also @ObservedObject var clientViewModel: ClientViewModel as a parameter?这是否意味着我还需要将@ObservedObject var clientViewModel: ClientViewModel作为参数传递?

My question is: Is this approach good or there is a better way to do this?我的问题是:这种方法好还是有更好的方法来做到这一点?

struct PurchaseView: View {
    @ObservedObject var purchaseViewModel: PurchaseViewModel
    @ObservedObject var itemViewModel: ItemViewModel

    var body: some View {
        VStack {
            Text(purchaseViewModel.title)
            ItemView(itemViewModel: itemViewModel)
        }
    }
}

class Purchase {
    let senderID: String
    let receiverID: String
    var status: PurchaseStatus
    var item: Item?
}

You could make the PurchaseViewModel contain the ItemViewModel and ClientViewModel as properties in the same way that the PurchaseView contains the ItemView and ClientView .您可以让PurchaseViewModel包含ItemViewModelClientViewModel作为属性,就像PurchaseView包含ItemViewClientView一样。

That would make PurchaseViewModel responsible for creating the instances of the other view models.这将使PurchaseViewModel负责创建其他视图模型的实例。 The parent of PurchaseView would no longer need to know about the implementation of PurchaseView . PurchaseView的父级不再需要了解PurchaseView的实现。

You should start by considering the relationship of the models , not the view models .您应该首先考虑模型的关系,而不是视图模型

For example, you could make a case that a Purchase involves one or more items ( Item ) and a purchaser ( Client ).例如,您可以假设Purchase涉及一个或多个项目 ( Item ) 和购买者 ( Client )。 In this case you would actually create a model something like:在这种情况下,您实际上会创建一个 model 类似于:

class Purchase {
    var items = [Item]()
    var client: Client
    ...
}

And your PurchaseViewModel would reflect this, containing the ItemViewModel and ClientViewModel您的PurchaseViewModel将反映这一点,包含ItemViewModelClientViewModel

    let clientViewModel: ClientViewModel
    let itemsViewModels: [ItemViewModel]

    init(purchase: Purchase) {
        self.clientViewModel = ClientViewModel(client:purchase.client)
        self.itemsViewModels = purchase.items.map { ItemViewModel(item:$0) }
    }

If you have a hierarchy of views that need some unrelated models then you can consider using the environment, especially for models that are "global"如果您有需要一些不相关模型的视图层次结构,那么您可以考虑使用环境,特别是对于“全局”模型

For example, say that the user was looking at an item detail, but they were not yet making a purchase (So there is no Purchase yet) and you want to have a button that shows them their Client detail.例如,假设用户正在查看项目详细信息,但他们还没有进行购买(因此还没有Purchase ),并且您希望有一个按钮向他们显示他们的Client详细信息。

You could pass the ItemViewModel explicitly to the ItemDetailView :您可以将ItemViewModel显式传递给ItemDetailView

struct ItemListView {
   ...

   Button(action: { ItemDetailView(item:someItemView) }) 
       { ... }

}


struct ItemDetailView {
    ...
    Button(action: { ClientView() }) {
        Text("Client detail")
    }
}

struct ClientDetailView {

   @EnvironmentObject client: ClientViewModel
   ...
}

You can inject the ClientViewModel into the environment at a suitable point, such as the root view or even scene delegate.您可以在合适的位置将ClientViewModel注入到环境中,例如根视图甚至场景委托。

If you have a hierarchy of views that need these models, but not all views need all models, you could use the environment to provide the various models rather than directly injecting them via initialiser parameters.如果您有需要这些模型的视图层次结构,但并非所有视图都需要所有模型,您可以使用环境来提供各种模型,而不是通过初始化参数直接注入它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM