From f4bb68696cf22e7a3b696cd8feb7bba8ecee2843 Mon Sep 17 00:00:00 2001 From: Krunoslav Zaher Date: Sun, 7 Feb 2016 21:22:12 +0100 Subject: [PATCH] Adds timer and interval to `Driver`. --- RxCocoa/Common/CocoaUnits/Driver/Driver.swift | 48 +++++++++++ Tests/RxCocoaTests/Driver+Test.swift | 82 +++++++++++++++++++ 2 files changed, 130 insertions(+) diff --git a/RxCocoa/Common/CocoaUnits/Driver/Driver.swift b/RxCocoa/Common/CocoaUnits/Driver/Driver.swift index be6ec56a..d12f9393 100644 --- a/RxCocoa/Common/CocoaUnits/Driver/Driver.swift +++ b/RxCocoa/Common/CocoaUnits/Driver/Driver.swift @@ -150,6 +150,41 @@ extension Driver { } } +extension Driver where Element : SignedIntegerType { + /** + Returns an observable sequence that produces a value after each period, using the specified scheduler to run timers and to send out observer messages. + + - seealso: [interval operator on reactivex.io](http://reactivex.io/documentation/operators/interval.html) + + - parameter period: Period for producing the values in the resulting sequence. + - returns: An observable sequence that produces a value after each period. + */ + @warn_unused_result(message="http://git.io/rxs.uo") + public static func interval(period: RxTimeInterval) + -> Driver { + return Driver(Observable.interval(period, scheduler: driverObserveOnScheduler)) + } +} + +// MARK: timer + +extension Driver where Element: SignedIntegerType { + /** + Returns an observable sequence that periodically produces a value after the specified initial relative due time has elapsed, using the specified scheduler to run timers. + + - seealso: [timer operator on reactivex.io](http://reactivex.io/documentation/operators/timer.html) + + - parameter dueTime: Relative time at which to produce the first value. + - parameter period: Period to produce subsequent values. + - returns: An observable sequence that produces a value after due time has elapsed and then each period. + */ + @warn_unused_result(message="http://git.io/rxs.uo") + public static func timer(dueTime: RxTimeInterval, period: RxTimeInterval) + -> Driver { + return Driver(Observable.timer(dueTime, period: period, scheduler: driverObserveOnScheduler)) + } +} + /** This method can be used in unit tests to ensure that driver is using mock schedulers instead of maind schedulers. @@ -165,9 +200,22 @@ public func driveOnScheduler(scheduler: SchedulerType, action: () -> ()) { action() + // If you remove this line , compiler buggy optimizations will change behavior of this code + _forceCompilerToStopDoingInsaneOptimizationsThatBreakCode(driverObserveOnScheduler) + _forceCompilerToStopDoingInsaneOptimizationsThatBreakCode(driverSubscribeOnScheduler) + // Scary, I know + driverObserveOnScheduler = originalObserveOnScheduler driverSubscribeOnScheduler = originalSubscribeOnScheduler } +func _forceCompilerToStopDoingInsaneOptimizationsThatBreakCode(scheduler: SchedulerType) { + let a: Int32 = 1 + let b = 314 + Int32(rand() & 1) + if a == b { + print(scheduler) + } +} + var driverObserveOnScheduler: SchedulerType = MainScheduler.instance var driverSubscribeOnScheduler: SchedulerType = ConcurrentMainScheduler.instance diff --git a/Tests/RxCocoaTests/Driver+Test.swift b/Tests/RxCocoaTests/Driver+Test.swift index 5d538acf..9d736ae2 100644 --- a/Tests/RxCocoaTests/Driver+Test.swift +++ b/Tests/RxCocoaTests/Driver+Test.swift @@ -1070,4 +1070,86 @@ extension DriverTest { XCTAssertEqual(results, [0, 1, 2, -1]) } +} + +//MARK: interval +extension DriverTest { + func testAsDriver_interval() { + let testScheduler = TestScheduler(initialClock: 0) + + let firstObserver = testScheduler.createObserver(Int) + let secondObserver = testScheduler.createObserver(Int) + + var disposable1: Disposable! + var disposable2: Disposable! + + driveOnScheduler(testScheduler) { + let interval = Driver.interval(100) + + testScheduler.scheduleAt(20) { + disposable1 = interval.asObservable().subscribe(firstObserver) + } + + testScheduler.scheduleAt(170) { + disposable2 = interval.asObservable().subscribe(secondObserver) + } + + testScheduler.scheduleAt(230) { + disposable1.dispose() + disposable2.dispose() + } + + testScheduler.start() + } + + XCTAssertEqual(firstObserver.events, [ + next(120, 0), + next(220, 1) + ]) + XCTAssertEqual(secondObserver.events, [ + next(170, 0), + next(220, 1) + ]) + } +} + +//MARK: timer +extension DriverTest { + func testAsDriver_timer() { + let testScheduler = TestScheduler(initialClock: 0) + + let firstObserver = testScheduler.createObserver(Int) + let secondObserver = testScheduler.createObserver(Int) + + var disposable1: Disposable! + var disposable2: Disposable! + + driveOnScheduler(testScheduler) { + let interval = Driver.timer(100, period: 105) + + testScheduler.scheduleAt(20) { + disposable1 = interval.asObservable().subscribe(firstObserver) + } + + testScheduler.scheduleAt(170) { + disposable2 = interval.asObservable().subscribe(secondObserver) + } + + testScheduler.scheduleAt(230) { + disposable1.dispose() + disposable2.dispose() + } + + testScheduler.start() + } + + XCTAssertEqual(firstObserver.events, [ + next(120, 0), + next(225, 1) + ]) + XCTAssertEqual(secondObserver.events, [ + next(170, 0), + next(225, 1) + ]) + } } \ No newline at end of file