快速合并:将三个信号合并为一个

时间:2020-04-04 21:02:49

标签: ios swift combine

我正在处理一个遗留库,在其中我不能随意修改其代码,并且正在尝试使用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>

1 个答案:

答案 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函数的结果转换为错误,则需要进一步的运算符,但这又很容易。)