我正在处理一个遗留库,在其中我不能随意修改其代码,并且正在尝试使用Combine将它们编织成更易于使用的东西。我的情况是方法调用可以返回一个响应,也可以返回一个响应和两个通知。仅响应是成功方案,响应+ 2通知是错误方案。我想将来自两个通知的响应和有效负载组合成一个错误,然后将其传递给我的应用程序。真正有趣的是,我不能保证响应或通知是最先到达的,也不是哪个通知是最先到达的。通知与响应位于不同的线程中。好消息是它们“几乎同时出现”。
我要处理通知,
firstNotificationSink = notificationCenter.publisher(for: .firstErrorPart, object: nil)
.sink { [weak self] notification in
// parse and get information about the error
}
secondNotificationSink = notificationCenter.publisher(for: .secondErrorPart, object: nil)
.sink { [weak self] notification in
// parse and get more information about the error
}
并要求旧式图书馆作出回应:
func doJob() -> String {
let resultString = libDoStuff(reference)
}
在给定的50ms时间范围内,我是否可以使用Combine将这三个信号合并为一个信号?意思是,如果我得到结果和两个通知,则我可以将错误响应传递给我的应用程序;如果我只有结果并且在50ms内没有通知到达,那么我可以将该成功响应传递给我的应用程序? / p>
答案 0 :(得分:1)
关于组合三个信号的部分很简单:使用.zip
。那不是很有趣。问题的有趣部分是您想要一个管道,用于发出通知是否在特定时限内到达通知。这是一个操作方法的示例(我没有使用您的实际数字,这只是一个演示):
import UIKit
import Combine
enum Ooops : Error { case oops }
class ViewController: UIViewController {
var storage = Set<AnyCancellable>()
override func viewDidLoad() {
super.viewDidLoad()
print("start")
NotificationCenter.default.publisher(for: Notification.Name("yoho"))
.map {_ in true}
.setFailureType(to: Ooops.self)
.timeout(0.5, scheduler: DispatchQueue.main) { Ooops.oops }
.replaceError(with: false)
.sink {print($0)}
.store(in: &self.storage)
DispatchQueue.main.asyncAfter(deadline:.now()+0.2) {
NotificationCenter.default.post(name: Notification.Name("yoho"), object: self)
}
}
}
如果asyncAfter
延迟为0.2
,则得到true
(紧随false
之后,但这并不重要;如果需要,可以更改此值)。如果延迟为0.9
,我们得到false
。因此,关键是,我们获得的 first 值可以正确地区分我们是否在要求的时间内收到信号。
好吧,所以其余的都是微不足道的:就像我之前所说的,您只需用.zip
连接三个信号即可。在所有三个发布者发出他们的 first 信号之后,它会发出一个元组-这就是您需要的所有信息,因为您已经从方法调用加上Bools获得了结果告诉您通知是否在时限内到达。现在,您可以阅读该元组并对其进行分析,然后随心所欲地做。 .zip
运算符具有映射功能,因此您可以按顺序发出分析结果。 (如果您想将map函数的结果转换为错误,则需要进一步的运算符,但这又很容易。)