我有这样的用例,我有一个父视图和一个子视图。两个视图都有自己对应的 ViewModel。
家长视图:
struct ParentView: View {
@StateObject var parentViewModel = ParentViewModel()
var body: some View {
NavigationView {
List {
TextField("Add Name", text: $parentViewModel.newListName)
NavigationLink(destination: ChildView()) {
Label("Select Products", systemImage: K.ListIcons.productsNr)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
父视图模型:
class ParentViewModel: ObservableObject {
@Published var newListName: String = ""
func saveList() {
// some logic to save to CoreData, method would be called via a button
// how do I reference "someString" from ChildViewModel in this ViewModel?
}
}
Run Code Online (Sandbox Code Playgroud)
子视图:
struct ChildView: View {
@StateObject var childViewModel = ChildViewModel()
var body: some View {
NavigationView {
List{
Text("Some element")
.onTapGesture {
childViewModel.alterData()
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
子视图模型:
class ChildViewModel: ObservableObject {
@Published var someString: String = ""
func alterData() {
someString = "Toast"
}
}
Run Code Online (Sandbox Code Playgroud)
我现在的问题是,如何将“someString”的新值从 ChildViewModel 传递到 ParentViewModel,以便用它做一些进一步的事情?我尝试@StateObject var childViewModel = ChildViewModel()
在 ParentViewModel 中创建引用,但这显然不起作用,因为这将创建 ChildViewModel 的新实例,因此不知道对“someString”所做的更改
解决方案:
按照 Josh 的建议,我采用了使用单个 ViewModel 而不是两个的方法。为了实现这一点,ParentView 需要一个.environmentObject(T)
修饰符。
家长视图:
struct ParentView: View {
@StateObject var parentViewModel = ParentViewModel()
var body: some View {
NavigationView {
List {
TextField("Add Name", text: $parentViewModel.newListName)
NavigationLink(destination: ChildView()) {
Label("Select Products", systemImage: K.ListIcons.productsNr)
}
}
}.environmentObject(parentViewModel)
}
Run Code Online (Sandbox Code Playgroud)
然后 ChildView 通过@EnvironmentObject
不使用初始值设定项来引用该环境对象:
struct ChildView: View {
@EnvironmentObject var parentViewModel: ParentViewModel
var body: some View {
NavigationView {
List{
Text("Some element")
.onTapGesture {
parentViewModel.alterData()
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
小智 1
对于这种情况,您很可能会使用绑定:
struct ChildView: View {
@Binding var name: String
var body: some View {
NavigationView {
List{
Text("Some element")
.onTapGesture {
name = "Altered!"
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
在父级中:
struct ParentView: View {
@StateObject var parentViewModel = ParentViewModel()
var body: some View {
NavigationView {
List {
TextField("Add Name", text: $parentViewModel.newListName)
NavigationLink(destination: ChildView(name: $parentViewModel.newListName)) {
Label("Select Products", systemImage: K.ListIcons.productsNr)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
另外,我认为您可以NavigationView
从 中删除视图ChildView
。拥有它就ParentView
足够了。