如何制作一个在组合中发送多个值的发布者

Posted

技术标签:

【中文标题】如何制作一个在组合中发送多个值的发布者【英文标题】:How to make a Publisher that sends multiple values in Combine 【发布时间】:2021-11-05 11:24:17 【问题描述】:

您能帮我解决合并问题吗?

我想创建一个在其生命周期内发送多个值的发布者。更详细地说,我想将带有完成处理程序的方法包装到发布者中,并且完成处理程序应该被多次调用。例如,它是一种用于通过 WebSocket 接收消息的方法,如下所示:

webSocketClient.receiveMessage  message, error in
    // this closure is called multiple times, everytime a message comes
    ...

如何将其包装到 Publisher 中?最后我想要AnyPublisher<String, Error> 这样的东西。

当我使用其他 FRP 库时,包装这些非常容易。例如,在 ReactiveSwift 中,可以使用SignalProducer.init(_ startHandler:) 来实现。在 RxSwift 中,它是 Observable.create 方法。

在Combine 中,我发现Future 可以在只有一个值要发出时使用,但它不适合我目前的情况。对于这个用例,我找不到 Publisher 的任何初始化程序。

另外,我在 TCA(可组合架构)中找到了可用于这种情况的 Effect.run。似乎在其实现中使用了自定义发布者,这对于简单的使用来说似乎有点复杂,但这是唯一的方法吗?还有其他简单的方法可以实现类似的行为吗?

我觉得这是一个很常见的场景,所以我想知道Combine用户在实践中是如何处理这种情况的。

提前谢谢你!

【问题讨论】:

【参考方案1】:

基本上有两种选择。

在 SwiftUI 环境中,使包含代码的类符合 ObservableObject 并添加 @Published 属性

class ViewModel : ObservableObject 
      @Published var message = ""

      func loadData() 
          webSocketClient.receiveMessage  message, error in
              self.message = message
              ...
          
      
  

在视图中创建视图模型的@StateObject 以接收有关新消息的通知。

或者用send 值声明一个主题

class ViewModel 
      let subject = PassthroughSubject<String,Never>()

      func loadData() 
          webSocketClient.receiveMessage  message, error in
              self.subject.send(message)
              ...
          
      
  

要接收通知获取类的实例,请在主题上调用 sink 并将结果存储到强引用中。

【讨论】:

我明白了。我可以理解,通过引入主题或其他变量是可能的。但是,不引入它们是否可以? 例如,在 RxSwift 中,可以像这样不引入另一个变量。这在Combine中不可能吗? swift let observable = Observable.create observer in webSocketClient.receiveMessage message, error in observer.on(.next(message)) ... let observable =... 也是一个变量。 不必如此。 Observable.create ....subscribe ... 也是可能的。

以上是关于如何制作一个在组合中发送多个值的发布者的主要内容,如果未能解决你的问题,请参考以下文章

并行/组合多个 64 位值的按位排列

查找特定值的组合

在Javascript中组合多个值的数字范围

在graphql中,组合多个源中的字段共享一个共同值的多个源的最佳方法是啥?

如何制作将生成 SQL 以在一条语句中插入多个值的 HQL?

如何制作在一段时间内每天组合多个条目的折线图?