首页 > 解决方案 > 如何在 ReactiveCocoa 9.0 中使用 SignalProducer.timer

问题描述

我正在将应用程序从 Swift 3 更新到 Swift 5。这需要更新 ReactiveCocoa。有一些代码SignalProducer在更新时不再工作。这是之前和之后:

斯威夫特 3 代码

func start(beats: [Beat]) -> SignalProducer<PlayedBeat, Error> {
  var index: Int = 0
  let oneSecondTimer = timer(interval: DispatchTimeInterval.seconds(1), on: QueueScheduler(), leeway: DispatchTimeInterval.milliseconds(100))
    .on(starting: {
      // initialize
      index = -1
    }, value: { date in
      index += 1
    })
    .flatMap(.latest) { [weak self] (_: Date) -> SignalProducer<PlayedBeat, Error> in
      guard let strongSelf = self else {
        return SignalProducer<PlayedBeat, Error>(error: Error.unknown("self reference missing"))
      }
      if index < beats.count {
        let data = beats[index].toDeviceFormat()
        strongSelf.device.writeRate(data: data, delegate: strongSelf)
        return SignalProducer<PlayedBeat, Error>(value: "boom")
      } else {
        return SignalProducer<PlayedBeat, Error>(error: Error.noMoreData).delay(1.0, on: QueueScheduler.main)
      }
  }

  let startSignal = SignalProducer<PlayedBeat, Error> { [weak self] (innerSink, disposable) in
    guard let strongSelf = self else {
      innerSink.send(error: Error.unknown("self reference missing"))
      return
    }
    strongSelf.beatSink = innerSink

    let beatDisposable = oneSecondTimer.observe(innerSink, during: strongSelf.reactive.lifetime)

    disposable += {
      let data = DatedBeat.stopPlayingDeviceFormat()
      strongSelf.device.writeRate(data: data, delegate: strongSelf)
    }
    disposable.add(beatDisposable)
  }


  return startSignal
    .on(
      started: { _ in
        print("Start sending beats")
    },
      failed: { (error) in
        print("error \(error)")
    },
      completed: { _ in
        print("completed stopped beating ")
    })
}

斯威夫特 5 代码

func start(beats: [DatedBeat]) -> SignalProducer<PlayedBeat, Error> {
  var index: Int = 0
  let oneSecondTimer = SignalProducer.timer(interval: DispatchTimeInterval.seconds(1), on: QueueScheduler.main, leeway: DispatchTimeInterval.milliseconds(100))
    .on(starting: {
      // initialize
      index = -1
    }, value: { date in
      index += 1
    })
    .flatMap(.latest) { [weak self] (_: Date) -> SignalProducer<PlayedBeat, Error> in
      guard let strongSelf = self else {
        return SignalProducer<PlayedBeat, Error>(error: Error.unknown("self reference missing"))
      }
      if index < beats.count {
        let data = beats[index].toDeviceFormat()
        strongSelf.device.writeRate(data: data, delegate: strongSelf)
        return SignalProducer<PlayedBeat, Error>(value: "boom")
      } else {
        return SignalProducer<PlayedBeat, Error>(error: Error.noMoreData)
          .delay(1.0, on: QueueScheduler.main)
      }
  }

  let startSignal = SignalProducer<PlayedBeat, Error> { [weak self] (innerSink, lifetime) in
    guard let strongSelf = self else {
      innerSink.send(error: Error.unknown("self reference missing"))
      return
    }
    strongSelf.beatSink = innerSink

    if lifetime.hasEnded {
      let data = DatedBeat.stopPlayingDeviceFormat()
      strongSelf.device.writeRate(data: data, delegate: strongSelf)
      innerSink.sendInterrupted()
      return
    }

    _ = oneSecondTimer.observe(on: innerSink as! Scheduler)
  }

  return startSignal.on(
    started: {
      print("Start sending beats")
  },
    failed: { (error) in
      print("error \(error)")
  },
    completed: {
      print("completed stopped beating ")
  })
}

目前,该行在_ = oneSecondTimer.observe(on: innerSink as! Scheduler)尝试 case innerSinkto时会引发错误Scheduler。如果我删除那条线,那么计时器永远不会启动。

如果有人对在 ReactiveCocoa 中启动计时器的正确方法有想法,那将非常有帮助。谢谢!

标签: iosswifttimerreactive-cocoa

解决方案


推荐阅读