From 8797a05a0e198f51cc8aabc79b071ee1f321901b Mon Sep 17 00:00:00 2001 From: Krunoslav Zaher Date: Wed, 15 Jun 2016 23:05:21 +0200 Subject: [PATCH] Improves `drive` documentation. --- .../Driver/Driver+Subscription.swift | 21 ++++++++++++++----- .../Common/CocoaUnits/UIBindingObserver.swift | 2 +- RxSwift/Schedulers/MainScheduler.swift | 4 ++-- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/RxCocoa/Common/CocoaUnits/Driver/Driver+Subscription.swift b/RxCocoa/Common/CocoaUnits/Driver/Driver+Subscription.swift index d56f8cb3..1a057049 100644 --- a/RxCocoa/Common/CocoaUnits/Driver/Driver+Subscription.swift +++ b/RxCocoa/Common/CocoaUnits/Driver/Driver+Subscription.swift @@ -11,9 +11,13 @@ import Foundation import RxSwift #endif +private let driverErrorMessage = "`drive*` family of methods can be only called from `MainThread`.\n" + +"This is required to ensure that the last replayed `Driver` element is delivered on `MainThread`.\n" + extension DriverConvertibleType { /** Creates new subscription and sends elements to observer. + This method can be only called from `MainThread`. In this form it's equivalent to `subscribe` method, but it communicates intent better. @@ -22,18 +26,20 @@ extension DriverConvertibleType { */ @warn_unused_result(message="http://git.io/rxs.ud") public func drive(observer: O) -> Disposable { - MainScheduler.ensureExecutingOnScheduler() + MainScheduler.ensureExecutingOnScheduler(driverErrorMessage) return self.asObservable().subscribe(observer) } /** Creates new subscription and sends elements to variable. + This method can be only called from `MainThread`. - parameter variable: Target variable for sequence elements. - returns: Disposable object that can be used to unsubscribe the observer from the variable. */ @warn_unused_result(message="http://git.io/rxs.ud") public func drive(variable: Variable) -> Disposable { + MainScheduler.ensureExecutingOnScheduler(driverErrorMessage) return drive(onNext: { e in variable.value = e }) @@ -41,13 +47,14 @@ extension DriverConvertibleType { /** Subscribes to observable sequence using custom binder function. + This method can be only called from `MainThread`. - parameter with: Function used to bind elements from `self`. - returns: Object representing subscription. */ @warn_unused_result(message="http://git.io/rxs.ud") public func drive(transformation: Observable -> R) -> R { - MainScheduler.ensureExecutingOnScheduler() + MainScheduler.ensureExecutingOnScheduler(driverErrorMessage) return transformation(self.asObservable()) } @@ -59,18 +66,21 @@ extension DriverConvertibleType { return with(self)(curriedArgument) } + This method can be only called from `MainThread`. + - parameter with: Function used to bind elements from `self`. - parameter curriedArgument: Final argument passed to `binder` to finish binding process. - returns: Object representing subscription. */ @warn_unused_result(message="http://git.io/rxs.ud") public func drive(with: Observable -> R1 -> R2, curriedArgument: R1) -> R2 { - MainScheduler.ensureExecutingOnScheduler() + MainScheduler.ensureExecutingOnScheduler(driverErrorMessage) return with(self.asObservable())(curriedArgument) } /** Subscribes an element handler, a completion handler and disposed handler to an observable sequence. + This method can be only called from `MainThread`. Error callback is not exposed because `Driver` can't error out. @@ -83,19 +93,20 @@ extension DriverConvertibleType { */ @warn_unused_result(message="http://git.io/rxs.ud") public func drive(onNext onNext: ((E) -> Void)? = nil, onCompleted: (() -> Void)? = nil, onDisposed: (() -> Void)? = nil) -> Disposable { - MainScheduler.ensureExecutingOnScheduler() + MainScheduler.ensureExecutingOnScheduler(driverErrorMessage) return self.asObservable().subscribe(onNext: onNext, onCompleted: onCompleted, onDisposed: onDisposed) } /** Subscribes an element handler to an observable sequence. + This method can be only called from `MainThread`. - parameter onNext: Action to invoke for each element in the observable sequence. - returns: Subscription object used to unsubscribe from the observable sequence. */ @warn_unused_result(message="http://git.io/rxs.ud") public func driveNext(onNext: E -> Void) -> Disposable { - MainScheduler.ensureExecutingOnScheduler() + MainScheduler.ensureExecutingOnScheduler(driverErrorMessage) return self.asObservable().subscribeNext(onNext) } } diff --git a/RxCocoa/Common/CocoaUnits/UIBindingObserver.swift b/RxCocoa/Common/CocoaUnits/UIBindingObserver.swift index 8595a691..1dde828e 100644 --- a/RxCocoa/Common/CocoaUnits/UIBindingObserver.swift +++ b/RxCocoa/Common/CocoaUnits/UIBindingObserver.swift @@ -37,7 +37,7 @@ public class UIBindingObserver) { - MainScheduler.ensureExecutingOnScheduler() + MainScheduler.ensureExecutingOnScheduler("Element can be bound to user interface only on MainThread.") switch event { case .Next(let element): diff --git a/RxSwift/Schedulers/MainScheduler.swift b/RxSwift/Schedulers/MainScheduler.swift index dfda88c8..ed109df7 100644 --- a/RxSwift/Schedulers/MainScheduler.swift +++ b/RxSwift/Schedulers/MainScheduler.swift @@ -43,9 +43,9 @@ public final class MainScheduler : SerialDispatchQueueScheduler { /** In case this method is called on a background thread it will throw an exception. */ - public class func ensureExecutingOnScheduler() { + public class func ensureExecutingOnScheduler(errorMessage: String? = nil) { if !NSThread.currentThread().isMainThread { - rxFatalError("Executing on backgound thread. Please use `MainScheduler.instance.schedule` to schedule work on main thread.") + rxFatalError(errorMessage ?? "Executing on backgound thread. Please use `MainScheduler.instance.schedule` to schedule work on main thread.") } }