如何解决2 个 ObservableObjects 之间的数据通信
我有 2 个独立的 ObservableObject
,分别称为 viewmodel1
和 viewmodel2
。
@Published var strings: [String] = []
。
实现这一目标的推荐方法是什么?
解决方法
显然,对此有许多潜在的解决方案,例如前面提到的 NotificationCenter
和单例想法。
对我来说,这似乎是一个 Combine 非常有用的场景:
import SwiftUI
import Combine
class ViewModel1 : ObservableObject {
var cancellable : AnyCancellable?
func connect(_ publisher: AnyPublisher<[String],Never>) {
cancellable = publisher.sink(receiveValue: { (newStrings) in
print(newStrings)
})
}
}
class ViewModel2 : ObservableObject {
@Published var strings: [String] = []
}
struct ContentView : View {
@ObservedObject private var vm1 = ViewModel1()
@ObservedObject private var vm2 = ViewModel2()
var body: some View {
VStack {
Button("add item") {
vm2.strings.append("\(UUID().uuidString)")
}
ChildView(connect: vm1.connect)
}.onAppear {
vm1.connect(vm2.$strings.eraseToAnyPublisher())
}
}
}
struct ChildView : View {
var connect : (AnyPublisher<[String],Never>) -> Void
@ObservedObject private var vm2 = ViewModel2()
var body: some View {
Button("Connect child publisher") {
connect(vm2.$strings.eraseToAnyPublisher())
vm2.strings = ["Other strings","From child view"]
}
}
}
要对此进行测试,首先尝试按下“添加项目”按钮——您将在控制台中看到 ViewModel1
接收新值。
然后,尝试 Connect child publisher
按钮——现在,初始连接被取消,并为子 ViewModel2
的迭代建立新的连接。
为了让这个场景起作用,你总是需要引用 ViewModel1
和 ViewModel2
,或者至少是 connect
方法,正如我在{{ 1}}。您可以轻松地通过依赖注入甚至通过 ChildView
EnvironmentObject
也可以更改为代替 1 个连接,通过将 ViewModel1
设为 cancellable
并每次添加一个连接(如果您需要一个->多个场景)来拥有多个连接。
使用 Set<AnyCancellable>
将等式两边具有特定类型的想法解耦,因此将 AnyPublisher
连接到 ViewModel4
等同样容易。
我遇到了同样的问题,我发现这个方法很好用,只是使用了引用类型的想法,并利用了类的优势,比如使用共享类型!
import SwiftUI
struct ContentView: View {
@StateObject var viewModel2: ViewModel2 = ViewModel2.shared
@State var index: Int = Int()
var body: some View {
Button("update strings array of ViewModel2") {
viewModel2.strings.append("Hello" + index.description)
index += 1
}
}
}
class ViewModel1: ObservableObject {
static let shared: ViewModel1 = ViewModel1()
@Published var onReceiveViewModel2: Bool = Bool() {
didSet {
print("strings array of ViewModel2 got an update!")
print("new update is:",ViewModel2.shared.strings)
}
}
}
class ViewModel2: ObservableObject {
static let shared: ViewModel2 = ViewModel2()
@Published var strings: [String] = [String]() {
didSet { ViewModel1.shared.onReceiveViewModel2.toggle() }
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。