给定以下代码:
enum MyError: Error {
case someError
}
myButton.publisher(for: .touchUpInside).tryMap({ _ in
if Bool.random() {
throw MyError.someError
} else {
return "we're in the else case"
}
})
.replaceError(with: "replaced Error")
.sink(receiveCompletion: { (completed) in
print(completed)
}, receiveValue: { (sadf) in
print(sadf)
}).store(in: &cancellables)
每当我点击按钮,我得到we're in the else case
,直到Bool.random()
为真-现在抛出一个错误。我尝试了不同的事情,但我不能实现捕捉/替换/忽略错误,并在点击按钮后继续。
在代码示例中,我希望有以下输出
we're in the else case
we're in the else case
replaced Error
we're in the else case
...
而是在replaced error
之后得到finished
,并且不发出任何事件。
Edit给定一个带有AnyPublisher<String, Error>
的发布者,如何在发生错误时不完成将其转换为AnyPublisher<String, Never>
,即忽略原始发布者发出的错误?
8条答案
按热度按时间fdx2calv1#
有提到一部WWDC电影,相信是2019年的《在实践中合并》,6点24分左右开始看:https://developer.apple.com/wwdc19/721
是的,
.catch()
终止上游发布者(电影7:45),并将其替换为.catch
参数中的给定发布者,因此当使用Just()
作为替换发布者时,通常会导致.finished
被交付。如果原来的发布者在失败后继续工作,则需要一个涉及
.flatMap()
的构造(movie 9:34)。导致可能失败的操作符需要在.flatMap
内执行,如果需要,可以在那里处理。代替
在
.flatMap
中,你总是替换发行商,因此不关心替换发行商是否被.catch
终止,因为它已经是一个替换发行商,我们原来的上游发行商是安全的。这也是您的问题**Edit:**的答案,关于如何将
<Output, Error>
转换为<Output, Never>
,因为.flatMap
不输出任何错误,它的Never before and after the flatMap.所有与错误相关的步骤都封装在flatMap中。(提示检查Failure=Never
:如果您为.assign(to:)
获得了Xcode自动完成,那么我相信您有一个Failure=Never流,否则订阅者将不可用。ycl3bljg2#
我相信E.Coms的答案是正确的,但我会说得简单得多,处理错误而不导致管道在错误发生后停止处理值的关键是将错误处理发布器嵌套在
flatMap
中:输出:
您可以在操场上运行此示例。
关于OP的编辑:
Edit给定一个带有
AnyPublisher<String, Error>
的发布者,如何在发生错误时不完成将其转换为AnyPublisher<String, Never>
,例如忽略原始发布者发出的错误?你不能。
mzmfm0qo3#
为此,可以使用
catch
运算符和Empty
发布器:ldxq2e6h4#
只要插入flatMap如下,你可以实现你想要的
工作模型如下:
如果我们使用上面的例子,它可能是这样的:
在这里,您可以将
firstPublisher
替换为带一个参数的AnyPublisher。同样在这里,firstPublisher只有一个值,它只能产生一个值。但是如果你的发布者可以产生多个值,它将在所有值都发出之前完成。
q5iwbnjs5#
我也在为这个问题而挣扎,最后我找到了一个解决方案。需要理解的一点是,您无法从一个已完成的通量中恢复。解决方案是返回一个
Result
而不是Error
。对于阅读此线程并尝试编译代码的其他人,您需要从article导入代码(对于
button.publisher(for: .touchUpIsinde)
部分)。另外,下面的代码可以处理
PassthroughSubject
的错误,并且永远不会完成通量:不能直接使用
PassthroughSubject<String, MyError>()
,否则,通量将在错误发生时完成。p1tboqfb6#
我在Peter Friese的这篇文章中找到了不完成管道并优雅地处理错误的最佳方法:https://peterfriese.dev/posts/swiftui-combine-networking-errorhandling/,方法是使用此Publisher扩展方法将接收到的内容Map到Result:
然后你可以这样使用它:
qqrboqgw7#
我建议将
Publisher
与typealias Failure = Never
一起使用,并将输出作为可选结果:typealias Output = Result<YourSuccessType, YourFailtureType>
unftdfkk8#
发布服务器一直发射,直到完成或失败(出现错误),之后流将终止。
解决此问题的一种方法是将结果用作发布者类型
出版商
订户