微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

2 个 ObservableObjects 之间的数据通信

如何解决2 个 ObservableObjects 之间的数据通信

我有 2 个独立的 ObservableObject,分别称为 viewmodel1viewmodel2

viewmodel2一个字符串数组:

@Published var strings: [String] = []

每当修改该数组时,我都希望通知 viewmodel1

实现这一目标的推荐方法是什么?

解决方法

显然,对此有许多潜在的解决方案,例如前面提到的 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 的迭代建立新的连接。

为了让这个场景起作用,你总是需要引用 ViewModel1ViewModel2,或者至少是 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 举报,一经查实,本站将立刻删除。