ReactiveSwift:如何编写任务计划程序

时间:2016-11-03 10:59:43

标签: ios swift reactive-cocoa

我正在尝试创建一个调度程序来使用一些数据。

调度程序必须能够:

  • 每次手动消费数据时发送一个事件
  • 每次在上次消费后经过一段时间后自动消费数据时发送一个事件

我使用MutableProperty

对手动消费进行了建模
 let consume = MutableProperty<Void>()

我试图用SignalProducer

模拟自动消费
 let timer = SignalProducer<Void, NoError>

我可以第一次通过组合这两个生产者的最新值来消费这些数据,例如

SignalProducer.combineLatest(consume.producer, timer)
    .take(first: 1)
    .map() { _ in return () }

无论以哪种方式出现,手动消费或生产者都会自动发送价值。

我无法弄清楚我将如何永久地做到这一点。

有人可以帮忙吗?

2 个答案:

答案 0 :(得分:4)

您可以使用ReactiveSwift

中定义的全局计时器功能启动计时器
public func timer(interval: TimeInterval, on scheduler: DateSchedulerProtocol) -> SignalProducer<Date, NoError>

将计时器与消耗属性结合使用:

let interval = 10.0
let timerSignal: SignalProducer<Date, NoError> = timer(interval: interval, on: QueueScheduler.main)
let consume = MutableProperty<Void>()

timerSignal.combineLatest(with: consume.producer).startWithValues { (date, v) in
    print("triggered at time: \(date)")
}

这样,您可以通过设置消耗的value属性或等待计时器事件来手动触发打印块。

答案 1 :(得分:0)

您可以将计时器包装到 SignalProducer 中

func timerProducer() -> SignalProducer<Void, Never> {
    return SignalProducer<Void, Never> { observer, disposable in
        let timer = Timer(timeInterval: 10, repeats: true) { timer in
            if disposable.hasEnded {
                timer.invalidate()
            } else {
                observer.send(value: ())
            }
        }
        RunLoop.main.add(timer, forMode: .common)
    }
}

注意:如果你从非主线程启动这个生产者,你需要将它添加到 RunLoop。否则它不会被触发。