Получите доступ к последнему значению от SignalProducer после завершения - PullRequest
0 голосов
/ 03 мая 2018

У меня есть производитель сигнала, когда он завершается, я хотел бы знать, было ли отправлено значение, мне нужен только последний, кажется, так просто ...

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()

Я пытался сохранить значение в локальной переменной:

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 по-прежнему равно нулю ...

Ответы [ 2 ]

0 голосов
/ 04 мая 2018

Во-первых, вы действительно уверены, что хотите событие terminated?

В нормальных условиях поток событий заканчивается событием completed. Исключения составляют failed, когда произошел сбой, и interrupted, когда наблюдение было закончено до того, как поток мог нормально завершиться (например, отмена).

Второй: может ли ваш 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.

Примечание. Если мы отправим событие interrupted или failed, последнее значение 3 не будет отправлено , поскольку они для завершающих событий закорачивают нормальный поток.

Если ваш SignalProducer может выйти из строя, и вы все еще хотите получить последнее значение до сбоя, вы можете использовать flatMapError, чтобы игнорировать ошибку перед оператором last:

signal
  .flatMapError { _ in
    return .empty
  }
  .take(last: 1)
  .observe(observer)
0 голосов
/ 03 мая 2018

мой ответ:

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
})
...