【问题标题】:How to share published model between two view models in SwiftUI?如何在 SwiftUI 中的两个视图模型之间共享已发布的模型?
【发布时间】:2021-04-06 20:16:18
【问题描述】:

我试图在两个不同的视图模型中访问同一个共享模型。两个关联的视图都需要访问视图模型中的模型,并且需要编辑模型。所以我不能只使用 EnvironmentObject 来访问模型。

我可以通过视图将模型传递给视图模型,但这不会使两个模型版本保持同步。有什么东西可以像绑定一样工作吗?因为通过绑定我可以访问模型,但它不会在此视图中发布更改。

简化示例:

NavigationView 中的第一个视图与相邻的第二个视图:

struct ContentView1: View {
    @StateObject var contentView1Model = ContentView1Model()
    var body: some View {
        NavigationView {
            VStack{
                TextField("ModelName", text: $contentView1Model.model.name)
                NavigationLink(destination: ContentView2(model: contentView1Model.model)){
                    Text("ToContentView2")
                }
            }
        }
    }
}

class ContentView1Model: ObservableObject {
    @Published var model = Model()
    //Some methods that modify the model
}

需要访问模型的相邻视图 2:

struct ContentView2: View {
    @StateObject var contentView2Model: ContentView2Model
    
    init(model: Model) {
        self._contentView2Model = StateObject(wrappedValue: ContentView2Model(model: model))
    }
    
    var body: some View {
        TextField("ModelName", text: $contentView2Model.model.name)
    }
}

class ContentView2Model: ObservableObject {
    
    @Published var model: Model // Tried binding but this won't publish the changes.
    
    init(model: Model) {
        self.model = model
    }
}

型号:

struct Model {
    var name = ""
}

感谢您的帮助!

【问题讨论】:

  • 什么是Model
  • 谢谢,示例中就是这个名字。但在实际用例中,它会是一个更复杂的结构。

标签: ios swift model swiftui viewmodel


【解决方案1】:

好的,Model 是结构体,所以当你通过 ContentViewModeltoContentView2Model` 传递它时它只是被复制

ContentView2(model: contentView1Model.model)

在这种情况下,最好将模型作为独立的ObservableObject,因此它将通过引用从一个视图模型传递到另一个视图模型。

class Model: ObservableObject {
    @Published var name = ""
}

然后你可以在任何需要的子视图中注入和修改,比如

struct ContentView1: View {
    @StateObject var contentView1Model = ContentView1Model()
    var body: some View {
        NavigationView {
            VStack{
                ModelEditView(model: contentView1Model.model)       // << !!
                NavigationLink(destination: ContentView2(model: contentView1Model.model)){
                    Text("ToContentView2")
                }
            }
        }
    }
}

struct ContentView2: View {
    @StateObject var contentView2Model: ContentView2Model
    
    init(model: Model) {
        self._contentView2Model = StateObject(wrappedValue: ContentView2Model(model: model))
    }
    
    var body: some View {
        ModelEditView(model: contentView2Model.model)       // << !!
    }
}

struct ModelEditView: View {
    @ObservedObject var model: Model
    
    var body: some View {
        TextField("ModelName", text: $model.name)
    }
}

【讨论】:

  • 到目前为止一切都很好,但是如何将 ModelEditView 视图中的观察对象所做的更改发布到“父视图”?例如。如果 ContentView1 中有一个文本视图可以访问存储在模型中的名称。底层模型由 ModelEditView 更改,但它不会将更改发布到父视图。 THX
  • 编辑:找到解决方案。由于 swift 目前不支持嵌套的 ObservableObjects,因此您需要将 objectWillChange Publisher 传递给父对象。详情请看:stackoverflow.com/questions/58406287/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-23
  • 1970-01-01
  • 1970-01-01
  • 2010-10-22
  • 1970-01-01
  • 2016-06-15
相关资源
最近更新 更多