Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在Combine中处理发布服务器错误的最佳做法是什么?(从CoreLocation发布标题更新)_Ios_Swift_Core Location_Combine - Fatal编程技术网

Ios 在Combine中处理发布服务器错误的最佳做法是什么?(从CoreLocation发布标题更新)

Ios 在Combine中处理发布服务器错误的最佳做法是什么?(从CoreLocation发布标题更新),ios,swift,core-location,combine,Ios,Swift,Core Location,Combine,我一直在开发一个应用程序,其中有一个指南针,可以根据发布标题更改和创建出版商来处理这些更改来更新标题 我对反应式编程非常陌生,但我遇到的问题似乎是一个常见的问题,所以我想发布它,看看是否有人能提供帮助 有时它会工作一段时间,发布者会发布新的标题并更新UI,但随后就会停止工作。其他时候,它永远不会开始更新(在任何标题更新之前传递错误)。在任何一种情况下,事件都会停止,因为故障完成事件正在发送到发布服务器: func locationManager(_ manager: CLLocationMana

我一直在开发一个应用程序,其中有一个指南针,可以根据发布标题更改和创建出版商来处理这些更改来更新标题

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

有时它会工作一段时间,发布者会发布新的标题并更新UI,但随后就会停止工作。其他时候,它永远不会开始更新(在任何标题更新之前传递错误)。在任何一种情况下,事件都会停止,因为故障完成事件正在发送到发布服务器:

func locationManager(_ manager: CLLocationManager,
                     didFailWithError error: Error) {

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

    print("error: \(error.localizedDescription)")
}
首先,我试图找出这些错误是什么,以便我能更好地处理它们。。。这个错误真的值得停止发布服务器吗?我想知道在标题更新的中途会发生什么样的错误,因为标题更新会在错误发生后恢复,即使发布者停止了。我试着打印错误,但我得到的只是这个,似乎没有什么帮助:
错误:操作无法完成。(kCLErrorDomain错误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)

我意识到我无法将错误发送给发布者(这是我应该做的吗?为标题更新指定一个特定的发布者,该发布者从不发送错误?),而在订阅端处理它可能是一种最佳做法,或者有一些在错误后恢复的最佳做法。

正如您所指出的,当发生错误时,这将始终结束由现成操作员构建的联合管道。这是一个特性,不是bug。特别令人惊讶的是,即使使用了错误处理操作符,如
catch
replaceError
,管道也会终止

通过在
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

让myNumberPublisher=PassthroughSubject()
//外部管道永远不会出错(错误类型为never):
myNumberPublisher
.map(String.init)//转换为字符串
.flatMap{中的数字
//内部管道可能会出错:
URLSession.shared.dataTaskPublisher(用于:URL(字符串):https://square?n=\(数字)“)!)
.replaceError(带有“Oopsies”)
.map{“答案是\(答案)”中的答案}
}
.sink{打印结果(结果)}
myNumberPublisher.send(“5”)
//=>答案是25
myNumberPublisher.send(“3”)//此处假设端点错误
//=>答案是糟糕
myNumberPublisher.send(“6”)
//=>答案是36

要在您的案例中使用
flatMap
,向发布者提供服务的类可能会要求您在出现错误时请求新的发布者

或者,您可以修改
headingPublisher
,使其具有
Never
错误类型。如果按此方法操作,错误应由出售
headingPublisher
的对象处理

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

  • AnyPublisher
  • AnyPublisher

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

以下内容可能对*使用联合收割机有所帮助“这本书。这确实有助于我走上正确的道路,但我认为我现在需要学习更多,并尝试找到一些例子。我真的不知道你所说的内部和外部管道是什么意思,或者在这种情况下如何使用
flatMap
,而没有看到一个示例。此外,我不确定您所说的“修改您的
标题发布者
以获得
从不
错误类型”是什么意思,因此我将进一步研究这些问题,它们会有帮助,我一定会回来接受答案。谢谢这是一个很难的话题,也很难简明扼要地解释。我添加了一个简单的例子来帮助解释。如果您查看Combine内置发布服务器的文档,您会注意到其中一些被描述为“永不失败”。例如,
Just
publisher。当您通过调用
.eraseToAnyPublisher()
键入擦除一个未失败的发布服务器时,您将看到该发布服务器的类型将是
AnyPublisher
“尤其令人惊讶的是,即使您使用了错误处理操作符(如catch或replaceError),管道也会终止。”