在Combine中处理发布者错误的最佳实践是什么? (从CoreLocation发布标题更新)

我一直在开发一个带有指南针的应用程序,该应用程序基于this example更新其标题以发布标题更改,并基于this example用于创建发布者来处理这些更改。

我对反应式编程非常陌生,但是遇到的问题似乎是一个常见问题,因此我想发布它,看看是否有人可以提供帮助。

有时它会工作一段时间,发布者会发布新标题并更新UI,但随后会停止工作。在其他时候,它永远不会开始更新(在任何标题更新之前都会出现错误)。在这两种情况下,由于将失败完成事件发送给发布者,事件将停止是有道理的:

func locationmanager(_ manager: CLLocationmanager,didFailWithError error: Error) {

    headingPublisher.send(completion: Subscribers.Completion.failure(error))

    print("error: \(error.localizedDescription)")
}

首先,我试图弄清楚这些错误是什么,以便我可以尝试更好地处理它们...错误真的值得停止发布者吗?我想知道标题更新的中途会发生什么样的错误,因为标题发布会在错误发生后恢复,即使发布者停止了。我尝试打印错误,但是我得到的只是这个,似乎没有帮助: error: The operation couldn’t be completed. (kCLErrorDomain error 0.)

我在iOS方面并不出色,因此如果有人对如何获得更好的错误描述有任何建议,请告诉我。

第二,我想知道如何才能忽略订阅服务器上发布者的错误,如果那是我应该做的事情,那么即使发生错误,.sink也将继续获取标题更新。这是基于示例的以下我的发布者代码:

    _ = headingProxy
        .publisher
        .receive(on: RunLoop.main)
        .sink(receiveCompletion: { completion in },receiveValue: { [weak self] (heading) in
                self?.currentHeadingaccuracy = heading.headingaccuracy
                self?.currentHeading = heading.trueHeading
        })
        .store(in: &cancellableSet)

我意识到我永远无法将错误发送给发布者(这是我应该做的吗?有一个专门的发布者来完成标题更新,而从不发送错误?),但我假设进行此发送的人包括发送错误是有充分理由的,这对于发布者来说是错误的,并且可能是在订阅方面进行处理的最佳实践,或者存在一些在错误发生后进行恢复的最佳实践。

trydiy 回答:在Combine中处理发布者错误的最佳实践是什么? (从CoreLocation发布标题更新)

正如您所指出的那样,当发生错误时,将始终终止使用现成的运算符构建的Combine管道。这是一个功能,而不是错误。尤其令人惊讶的是,即使您使用catchreplaceError之类的错误处理运算符,流水线也会结束。

您可以通过包装可能在flatMap中发生错误的管道的任何部分来使管道对错误具有弹性。

将主管道视为“外部”管道,并将包裹在flatMap中的管道视为“内部”管道。确保外部管道的错误类型为Never,并且它可以永远继续处理值。

考虑一个返回数字平方的端点:

let myNumberPublisher = PassthroughSubject<Int,Never>()

// Outer pipeline will never error (the Error type is Never):
myNumberPublisher
  .map(String.init) // convert to string
  .flatMap { number in
    // Inner pipeline can error:
    URLSession.shared.dataTaskPublisher(for: URL(string: "https://square?n=\(number)")!)
      .replaceError(with: "Oopsies")
      .map { answer in "The answer is \(answer)" }
  }
  .sink { result in print(result) }

myNumberPublisher.send("5")
// => The answer is 25
myNumberPublisher.send("3") // assume the endpoint errors here
// => The answer is Oopsies
myNumberPublisher.send("6")
// => The answer is 36


要在您的情况下使用flatMap,出售发布者的类可能会要求您在发生错误时要求新的发布者。

或者,您可以将headingPublisher修改为具有Never错误类型。如果走这条路线,应该由出售headingPublisher的对象来处理错误。

另一种选择是向两个发布者出售,一个用于价值发布,另一种用于错误发布:

  • AnyPublisher<ValueType,Never>
  • AnyPublisher<Error,Never>

这些选项中的任何一个都可以使用,您选择的选项将取决于您的需求。

本文链接:https://www.f2er.com/2989253.html

大家都在问