SwiftUI:不同ViewModel之间的通信



我有一个包含两个子视图的父视图。每个子视图都会从父视图传递一个不同的EnvironmentObject。作为各种不同更改的表示,第二个子视图包含一个按钮,该按钮可用于调用其ViewModel中的函数,然后该函数应更改第一个子视图的ViewModel中一个变量。

struct ParentView: View {
@StateObject var viewModel_1: ViewModel_1
@StateObject var viewModel_2: ViewModel_2
var body: some View {
ZStack {
ChildView_1()
.environmentObject(viewModel_1)

ChildView_2()
.environmentObject(viewModel_2)
}
}}

struct ChildView_1: View {
@EnvironmentObject var viewModel_1: ViewModel_1
var body: some View {
...
}}

struct ChildView_2: View {
@EnvironmentObject var viewModel_2: ViewModel_2
var body: some View {
Button(action: {
viewModel_2.changeValue_in_ViewModel_1(value: 1)
}, label: {
Text("Tap to change value")
})
}}

class ViewModel_1: ObservableObject {
@Published var someValue: Int = 0
func changeValue(value: Int) -> Void {
self.someValue = value
}
}

class ViewModel_2: ObservableObject {
func changeValue_in_ViewModel_1(value: Int) -> Void {
//something like viewModel_2.changeValue(value: value)
}
}

有没有办法让这两个ViewModel能够相互通信?谢谢

只需ViewModel_2引用ViewModel_1即可解决。

但是,不必引用所有ViewModel_1,因此您可以使用协议仅分离所需的逻辑,并让ViewModel_2拥有它。

这是上面解释的示例代码。

搜索依赖项注入可以得到很多关于它的信息


struct ParentView: View {
@StateObject var viewModel_1: ViewModel_1
@StateObject var viewModel_2: ViewModel_2
init() {
let viewModel_1 = ViewModel_1()
_viewModel_1 = StateObject(wrappedValue: viewModel_1)
_viewModel_2 = StateObject(wrappedValue: ViewModel_2(changeValue: viewModel_1 as! ChangeValue))
}
var body: some View {
VStack {
ChildView_1()
.environmentObject(viewModel_1)
ChildView_2()
.environmentObject(viewModel_2)
}
}
}

struct ChildView_1: View {
@EnvironmentObject var viewModel_1: ViewModel_1
var body: some View {
Text("(viewModel_1.someValue)")
}
}

struct ChildView_2: View {
@EnvironmentObject var viewModel_2: ViewModel_2
@State var count: Int = 0
var body: some View {
Button(action: {
count = count + 1
viewModel_2.changeValue_in_ViewModel_1(value: count)
}, label: {
Text("Tap to change value")
})
}
}
protocol ChangeValue {
func changeValue(value: Int)
}
class ViewModel_1: ObservableObject, ChangeValue {
@Published var someValue: Int = 0
func changeValue(value: Int) -> Void {
self.someValue = value
}
}

class ViewModel_2: ObservableObject {
private let changeValue: ChangeValue
init (changeValue: ChangeValue) {
self.changeValue = changeValue
}
func changeValue_in_ViewModel_1(value: Int) -> Void {
//something like viewModel_2.changeValue(value: value)
changeValue.changeValue(value: value)
}
}

我们实际上并没有在SwiftUI中使用视图模型对象。View结构已经是一个视图模型了,作为一种值类型,它比对象更高效,也更不容易出错,但属性包装器使它表现得像对象,SwiftUI区分了视图结构,它在屏幕上为我们创建/更新了实际的UIView/NSViews。如果你使用实际的视图模型对象,你会遇到错误并面临问题。

您可以将相关的@State变量分组到它们自己的结构中,并使用mutating func进行逻辑。这样,它可以独立测试,但最好的是SwiftUI检测到结构的某个属性是对整个结构的更改,这使得它的依赖性跟踪速度极快。

environmentObject被设计为保存一个存储对象,该对象包含@Published属性中的模型结构(通常是数组(。environmentObject通常不超过一个。此对象通常负责持久化或同步模型数据。

最新更新