Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drive() and emit() for multiple observers #1962

Merged
merged 5 commits into from
Dec 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@
All notable changes to this project will be documented in this file.

---
## 6.0.0-beta.1

**Note**: RxSwift 6 and above has a minimum target of Swift 5.1 (Xcode 11)

* Remove `UIWebView` Reactive Extensions due to Apple hard deprecation. #2062
* Minimum Swift version is now 5.1. #2077
* Remove scoped imports in favor of library evolution. #2103
* Add `Driver.drive()` and `Signal.emit()` for multiple observers/relays. #1962
* Add `compactMap` to `SharedSequence`, `Single` and `Maybe`. #1978
* Add `UITextField.isSecureTextEntry` binder. #1968
* Remove "custom" `Result` in favor of `Foundation.Resault`. #2006
* Fix compilation error in `SharedSequence.createUnsafe`. #2014

## [5.0.1](https://github.com/ReactiveX/RxSwift/releases/tag/5.0.1)

* Reverts Carthage integration from using static to dynamic libraries. #1960
Expand Down
22 changes: 7 additions & 15 deletions RxCocoa/Common/Observable+Bind.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ extension ObservableType {
- returns: Disposable object that can be used to unsubscribe the observers.
*/
public func bind<Observer: ObserverType>(to observers: Observer...) -> Disposable where Observer.Element == Element {
return self.bind(to: observers)
return self.subscribe { event in
observers.forEach { $0.on(event) }
}
}

/**
Expand All @@ -28,20 +30,10 @@ extension ObservableType {
- returns: Disposable object that can be used to unsubscribe the observers.
*/
public func bind<Observer: ObserverType>(to observers: Observer...) -> Disposable where Observer.Element == Element? {
self.map { $0 as Element? }.bind(to: observers)
}

/**
Creates new subscription and sends elements to observer(s).
In this form, it's equivalent to the `subscribe` method, but it better conveys intent, and enables
writing more consistent binding code.
- parameter to: Observers to receives events.
- returns: Disposable object that can be used to unsubscribe the observers.
*/
private func bind<Observer: ObserverType>(to observers: [Observer]) -> Disposable where Observer.Element == Element {
self.subscribe { event in
observers.forEach { $0.on(event) }
}
return self.map { $0 as Element? }
.subscribe { event in
observers.forEach { $0.on(event) }
}
}

/**
Expand Down
25 changes: 17 additions & 8 deletions RxCocoa/Traits/Driver/Driver+Subscription.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,13 @@ extension SharedSequenceConvertibleType where SharingStrategy == DriverSharingSt
- parameter observer: Observer that receives events.
- returns: Disposable object that can be used to unsubscribe the observer from the subject.
*/
public func drive<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element {
public func drive<Observer: ObserverType>(_ observers: Observer...) -> Disposable where Observer.Element == Element {
MainScheduler.ensureRunningOnMainThread(errorMessage: errorMessage)
return self.asSharedSequence().asObservable().subscribe(observer)
return self.asSharedSequence()
.asObservable()
.subscribe { e in
observers.forEach { $0.on(e) }
}
}

/**
Expand All @@ -36,9 +40,14 @@ extension SharedSequenceConvertibleType where SharingStrategy == DriverSharingSt
- parameter observer: Observer that receives events.
- returns: Disposable object that can be used to unsubscribe the observer from the subject.
*/
public func drive<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element? {
public func drive<Observer: ObserverType>(_ observers: Observer...) -> Disposable where Observer.Element == Element? {
MainScheduler.ensureRunningOnMainThread(errorMessage: errorMessage)
return self.asSharedSequence().asObservable().map { $0 as Element? }.subscribe(observer)
return self.asSharedSequence()
.asObservable()
.map { $0 as Element? }
.subscribe { e in
observers.forEach { $0.on(e) }
}
}

/**
Expand All @@ -48,10 +57,10 @@ extension SharedSequenceConvertibleType where SharingStrategy == DriverSharingSt
- parameter relay: Target relay for sequence elements.
- returns: Disposable object that can be used to unsubscribe the observer from the relay.
*/
public func drive(_ relay: BehaviorRelay<Element>) -> Disposable {
public func drive(_ relays: BehaviorRelay<Element>...) -> Disposable {
MainScheduler.ensureRunningOnMainThread(errorMessage: errorMessage)
return self.drive(onNext: { e in
relay.accept(e)
relays.forEach { $0.accept(e) }
})
}

Expand All @@ -62,10 +71,10 @@ extension SharedSequenceConvertibleType where SharingStrategy == DriverSharingSt
- parameter relay: Target relay for sequence elements.
- returns: Disposable object that can be used to unsubscribe the observer from the relay.
*/
public func drive(_ relay: BehaviorRelay<Element?>) -> Disposable {
public func drive(_ relays: BehaviorRelay<Element?>...) -> Disposable {
MainScheduler.ensureRunningOnMainThread(errorMessage: errorMessage)
return self.drive(onNext: { e in
relay.accept(e)
relays.forEach { $0.accept(e) }
})
}

Expand Down
51 changes: 30 additions & 21 deletions RxCocoa/Traits/Signal/Signal+Subscription.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,56 +15,65 @@ extension SharedSequenceConvertibleType where SharingStrategy == SignalSharingSt

In this form it's equivalent to `subscribe` method, but it communicates intent better.

- parameter to: Observer that receives events.
- parameter to: Observers that receives events.
- returns: Disposable object that can be used to unsubscribe the observer from the subject.
*/
public func emit<Observer: ObserverType>(to observer: Observer) -> Disposable where Observer.Element == Element {
return self.asSharedSequence().asObservable().subscribe(observer)
public func emit<Observer: ObserverType>(to observers: Observer...) -> Disposable where Observer.Element == Element {
return self.asSharedSequence()
.asObservable()
.subscribe { event in
observers.forEach { $0.on(event) }
}
}

/**
Creates new subscription and sends elements to observer.

In this form it's equivalent to `subscribe` method, but it communicates intent better.

- parameter to: Observer that receives events.
- parameter to: Observers that receives events.
- returns: Disposable object that can be used to unsubscribe the observer from the subject.
*/
public func emit<Observer: ObserverType>(to observer: Observer) -> Disposable where Observer.Element == Element? {
self.asSharedSequence().asObservable().map { $0 as Element? }.subscribe(observer)
public func emit<Observer: ObserverType>(to observers: Observer...) -> Disposable where Observer.Element == Element? {
return self.asSharedSequence()
.asObservable()
.map { $0 as Element? }
.subscribe { event in
observers.forEach { $0.on(event) }
}
}

/**
Creates new subscription and sends elements to `BehaviorRelay`.
- parameter relay: Target relay for sequence elements.
- parameter to: Target relays for sequence elements.
- returns: Disposable object that can be used to unsubscribe the observer from the relay.
*/
public func emit(to relay: BehaviorRelay<Element>) -> Disposable {
self.emit(onNext: { e in
relay.accept(e)
public func emit(to relays: BehaviorRelay<Element>...) -> Disposable {
return self.emit(onNext: { e in
relays.forEach { $0.accept(e) }
})
}

/**
Creates new subscription and sends elements to `BehaviorRelay`.
- parameter relay: Target relay for sequence elements.
- parameter to: Target relays for sequence elements.
- returns: Disposable object that can be used to unsubscribe the observer from the relay.
*/
public func emit(to relay: BehaviorRelay<Element?>) -> Disposable {
self.emit(onNext: { e in
relay.accept(e)
public func emit(to relays: BehaviorRelay<Element?>...) -> Disposable {
return self.emit(onNext: { e in
relays.forEach { $0.accept(e) }
})
}

/**
Creates new subscription and sends elements to relay.

- parameter relay: Target relay for sequence elements.
- parameter to: Target relays for sequence elements.
- returns: Disposable object that can be used to unsubscribe the observer from the relay.
*/
public func emit(to relay: PublishRelay<Element>) -> Disposable {
self.emit(onNext: { e in
relay.accept(e)
public func emit(to relays: PublishRelay<Element>...) -> Disposable {
return self.emit(onNext: { e in
relays.forEach { $0.accept(e) }
})
}

Expand All @@ -74,9 +83,9 @@ extension SharedSequenceConvertibleType where SharingStrategy == SignalSharingSt
- parameter to: Target relay for sequence elements.
- returns: Disposable object that can be used to unsubscribe the observer from the relay.
*/
public func emit(to relay: PublishRelay<Element?>) -> Disposable {
self.emit(onNext: { e in
relay.accept(e)
public func emit(to relays: PublishRelay<Element?>...) -> Disposable {
return self.emit(onNext: { e in
relays.forEach { $0.accept(e) }
})
}

Expand Down
27 changes: 18 additions & 9 deletions Sources/AllTestz/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -238,16 +238,17 @@ final class DriverTest_ : DriverTest, RxTestCase {
("testDrivingOrderOfSynchronousSubscriptions1", DriverTest.testDrivingOrderOfSynchronousSubscriptions1),
("testDrivingOrderOfSynchronousSubscriptions2", DriverTest.testDrivingOrderOfSynchronousSubscriptions2),
("testDriveObserver", DriverTest.testDriveObserver),
("testDriveObservers", DriverTest.testDriveObservers),
("testDriveOptionalObserver", DriverTest.testDriveOptionalObserver),
("testDriveOptionalObservers", DriverTest.testDriveOptionalObservers),
("testDriveNoAmbiguity", DriverTest.testDriveNoAmbiguity),
("testDriveRelay", DriverTest.testDriveRelay),
("testDriveRelays", DriverTest.testDriveRelays),
("testDriveOptionalRelay1", DriverTest.testDriveOptionalRelay1),
("testDriveOptionalBehaviorRelays1", DriverTest.testDriveOptionalBehaviorRelays1),
("testDriveOptionalRelay2", DriverTest.testDriveOptionalRelay2),
("testDriveOptionalBehaviorRelays2", DriverTest.testDriveOptionalBehaviorRelays2),
("testDriveRelayNoAmbiguity", DriverTest.testDriveRelayNoAmbiguity),
("testDriveBehaviorRelay", DriverTest.testDriveBehaviorRelay),
("testDriveBehaviorRelay1", DriverTest.testDriveBehaviorRelay1),
("testDriveBehaviorRelay2", DriverTest.testDriveBehaviorRelay2),
("testDriveBehaviorRelay3", DriverTest.testDriveBehaviorRelay3),
] }
}

Expand Down Expand Up @@ -1928,16 +1929,24 @@ final class SignalTests_ : SignalTests, RxTestCase {
("testAsSignal_onErrorDriveWith", SignalTests.testAsSignal_onErrorDriveWith),
("testAsSignal_onErrorRecover", SignalTests.testAsSignal_onErrorRecover),
("testEmitObserver", SignalTests.testEmitObserver),
("testEmitObservers", SignalTests.testEmitObservers),
("testEmitOptionalObserver", SignalTests.testEmitOptionalObserver),
("testEmitOptionalObservers", SignalTests.testEmitOptionalObservers),
("testEmitNoAmbiguity", SignalTests.testEmitNoAmbiguity),
("testEmitBehaviorRelay", SignalTests.testEmitBehaviorRelay),
("testEmitBehaviorRelays", SignalTests.testEmitBehaviorRelays),
("testEmitBehaviorRelay1", SignalTests.testEmitBehaviorRelay1),
("testEmitBehaviorRelays1", SignalTests.testEmitBehaviorRelays1),
("testEmitBehaviorRelay2", SignalTests.testEmitBehaviorRelay2),
("testEmitBehaviorRelay3", SignalTests.testEmitBehaviorRelay3),
("testSignalRelay", SignalTests.testSignalRelay),
("testSignalOptionalRelay1", SignalTests.testSignalOptionalRelay1),
("testSignalOptionalRelay2", SignalTests.testSignalOptionalRelay2),
("testDriveRelayNoAmbiguity", SignalTests.testDriveRelayNoAmbiguity),
("testEmitBehaviorRelays2", SignalTests.testEmitBehaviorRelays2),
("testEmitBehaviorRelayNoAmbiguity", SignalTests.testEmitBehaviorRelayNoAmbiguity),
("testEmitPublishRelay", SignalTests.testEmitPublishRelay),
("testEmitPublishRelays", SignalTests.testEmitPublishRelays),
("testEmitOptionalPublishRelay1", SignalTests.testEmitOptionalPublishRelay1),
("testEmitOptionalPublishRelays", SignalTests.testEmitOptionalPublishRelays),
("testEmitOptionalPublishRelay2", SignalTests.testEmitOptionalPublishRelay2),
("testEmitPublishRelays2", SignalTests.testEmitPublishRelays2),
("testEmitPublishRelayNoAmbiguity", SignalTests.testEmitPublishRelayNoAmbiguity),
] }
}

Expand Down
Loading