使用CombineLatest 与可选发布者进行 Swift 组合

标签 swift combine

我是组合框架的新手,所以我的问题可能很简单。 我正在尝试合并来自多个发布商的值并发送值,即使收到的值是某些发布商尚未发布的值。

这是我现在所拥有的:

return Publishers
      .CombineLatest(somePublisher, otherPublisher)
      .map { (somePublisherValues, otherPublisherValue) in
        return [
          somePublisher,
          otherPublisherValue
        ]
      }
      .removeDuplicates()
      .eraseToAnyPublisher()

两家出版商在所有情况下都会发布,因此工作正常。 现在我需要添加第三个:thirdPublisher。

  • somePublisher 和thirdPublisher 都可以发布
  • 某些发布者可能不会发布
  • 第三发布者不得发布

如何在以前的情况下的所有情况下发送响应,例如:

  • 返回 [somePublisher、otherPublisherValue、thirdPublisherValue]
  • 返回 [nil、otherPublisherValue、thirdPublisherValue]
  • 返回 [somePublisher, otherPublisherValue, nil]

我尝试过:

return Publishers
      .CombineLatest3(somePublisher, otherPublisher, thirdPublisher)
      .map { (somePublisherValues, otherPublisherValue, thirdPublisherValue) in
        return [
          somePublisher,
          otherPublisherValue,
          thirdPublisher
        ]
      }
      .removeDuplicates()
      .eraseToAnyPublisher()

但它不会发布,因为一些发布者不在场。

最佳答案

CombineLatest 被设计为仅在其所有上游发布者发出第一个值后才发出。如果您希望在任何上游发出后立即发出并为所有缺失值发送 nil,您可以映射所有上游以发出 Optional 值并强制它们使用 prepend(nil) 在任何实际值之前发送 nil

这样,您将在实际输出之前收到一个 [nil, nil, ...] 值(您可以使用 dropFirst 忽略该值),然后您将开始收到所需的输出。

let publisher: PassthroughSubject<Int, Never> = .init()
let publisher2: PassthroughSubject<Int, Never> = .init()

let optionalPublisher = publisher.map(Optional.init).prepend(nil)
let optionalPublisher2 = publisher2.map(Optional.init).prepend(nil)

let combined = Publishers.CombineLatest(optionalPublisher, optionalPublisher2)

combined.sink {
  print("CombineLatest emitted \($0)")
}.store(in: &subscriptions)

publisher.send(1)
publisher2.send(1)
publisher.send(2)

输出:

CombineLatest emitted (nil, nil)
CombineLatest emitted (Optional(1), nil)
CombineLatest emitted (Optional(1), Optional(1))
CombineLatest emitted (Optional(2), Optional(1))

关于使用CombineLatest 与可选发布者进行 Swift 组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73950560/

相关文章:

ios - 组合:监听内部集合变化

ios - 导航栏上的常用栏按钮项

ios - 为什么我的线不旋转? -- CGContextRotateCTM

swift - 如何通过点击 TableViewCell 中的 CollectionView Cell 来使用 NavigationController

ios - 无法确定用户何时不允许定位服务

快速组合 : merge multiple publishers and emit `true` when any of them emits `true`

ios - 如何快速对数组中的自定义对象进行排序?

ios - 将 SwiftUI 按钮绑定(bind)到 AnySubscriber,例如 RxCocoa 的按钮点击

protocols - 如何使用@Published 属性包装器定义协议(protocol)以包含属性

ios - Combine + SwiftUI 中的最佳数据绑定(bind)实践?