终止时从SignalProducer访问最后一个值

时间:2018-05-03 08:46:09

标签: reactive-swift

我有一个信号发生器,当它终止时我想知道是否发送了一个值,我只需要最后一个,看起来很简单......

let myProducer: SignalProducer<MyObject, MyError> = getMyProducer()

myProducer.on(terminated: {

  // I need the last value here

  // Or I need to know if value was never called

}).start()

我试图将值存储在本地var:

let myProducer: SignalProducer<MyObject, MyError> = getMyProducer()
var myValue: MyObject?

myProducer.on(value: { value in

    myValue = value

}, terminated: {

    guard let value = myValue else {
        // value was never called
        return
    }
    // value was called

}).start()

但有时终止会在调用值时调用,但myValue仍然是nil ......

2 个答案:

答案 0 :(得分:1)

首先,您确定要进行terminated事件吗?

在正常情况下,事件流以completed事件结束。发生故障时的例外情况为failedinterrupted,当流程正常完成(例如取消)之前观察结束时。

第二:你的SignalProducer能否失败,而在失败的情况下,你是否还想在失败前发送最后一个值?

如果没有,它就像使用take(last:)运算符一样简单:

enum MyError: Error {
  case testError
}

let (signal, input) = Signal<Int, MyError>.pipe()

let observer = Signal<Int, MyError>.Observer(
  value: { print("value: \($0)") },
  failed: { print("error: \($0)") },
  completed: { print("completed") },
  interrupted: { print("interrupted") }
)


signal
  .take(last: 1)
  .observe(observer)


input.send(value: 1)   // Nothing printed
input.send(value: 2)   // Nothing printed
input.send(value: 3)   // Nothing printed
input.sendCompleted()  // value 3 printed

我在这里使用Signal因此我可以手动向其发送事件仅用于演示,同样适用于SignalProducer

注意:如果我们发送interruptedfailed事件,最后一个值3 将不会发送,因为那些终止事件会使正常流程短路。

如果您的SignalProducer可能失败,并且您仍希望在失败前获得最后一个值,则可以使用flatMapError忽略错误 {{1运营商:

last

答案 1 :(得分:-1)

我的回答:

producer
.flatMapError { _ in SignalProducer<Value, NoError>.empty }
.collect()
startWithResult( { result in
  case let .success(results):
    done(with: results.last)
  case let .failure(error):
    () // should not happen as errors are flatmapped
})