Combine:我可以用 nil 替换错误吗?

Combine: can I replace an error with nil?

在下面的示例中,永远不会打印“2”,因为错误是一个完成事件,阻止发布者发送更多事件。这对我来说很清楚。

import Combine

enum TestError: Error {
  case ohnoes
}

let publisher = PassthroughSubject<Int, Error>()

publisher
  .sink(receiveCompletion: { completion in
  print(completion)
}) { int in
  print(int)
}

publisher.send(1)
publisher.send(completion: .failure(TestError.ohnoes))
publisher.send(2)

遗憾的是,即使 replaceErrorcatch 也不会停止完成事件,因此管道仍将结束。

所以我的问题是,如何用 nil 值替换错误并防止完成事件?基本上我想将 AnyPublisher<Int, Error> 转换为 AnyPublisher<Int?, Never>,对于那些我根本不关心错误,只想继续接收未来值的情况。

使用 ReactiveKit 我有这个扩展:

extension Signal {
  func errorToOptional() -> Signal<Element?, Never> {
    return Signal<Element?, Never> { observer in
      self.observe { event in
        switch event {
        case .next(let element):
          observer.receive(element)
        case .failed:
          observer.receive(nil)
        case .completed:
          observer.receive(completion: .finished)
        }
      }
    }
  }
}

而且效果很好。但是 Combine 类型使得创建这样的扩展非常困难(如果不是不可能的话?)。

你说

publisher.send(completion: .failure(TestError.ohnoes))

发布者因此发出失败消息。那就是你告诉它要做的。如果发布者发出失败消息,则根据定义它已经死了。这就是失败在 Combine 中的意义。你不能在发布者的下游做任何会神奇地改变它的事情。

So my question is, how can I replace the error with a nil value and prevent the completion event?

您可以通过在发布者和捕获错误或将其转换为 Never 的接收器之间放置一些东西来防止错误(失败)到达接收器。但是您不能阻止发布者失败,因为那是您刚刚告诉它要做的。

Basically I want to transform AnyPublisher into AnyPublisher, for those cases where I simply don't care about the error at all, and just want to keep receiving future values.

此发布商不会有任何未来价值。它失败了。这就是发出错误 的意思 。这就是您告诉出版商要做的。