Implement Publisher and EventHub - subject that can’t error and publish sharing strategy

This commit is contained in:
Denys Telezhkin 2017-02-26 12:25:33 +02:00
parent e75496e02d
commit 6926375d1b
9 changed files with 311 additions and 2 deletions

View File

@ -274,6 +274,7 @@ custom_categories:
children:
- ControlEvent
- ControlProperty
- Publisher
- UIBindingObserver
- name: RxCocoa/Traits/Driver
children:
@ -283,9 +284,13 @@ custom_categories:
- Driver
- ObservableConvertibleType+Driver
- Variable+Driver
- name: RxCocoa/Traits/EventHub
children:
- EventHub
- name: RxCocoa/Traits/SharedSequence
children:
- ObservableConvertibleType+SharedSequence
- Publisher+SharedSequence
- SharedSequence+Operators+arity
- SharedSequence+Operators
- SharedSequence

View File

@ -23,6 +23,18 @@
1AF67DA81CED430100C310FA /* ReplaySubjectTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AF67DA51CED430100C310FA /* ReplaySubjectTest.swift */; };
271A97411CFC996B00D64125 /* UIViewController+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271A97401CFC996B00D64125 /* UIViewController+Rx.swift */; };
271A97441CFC9F7B00D64125 /* UIViewControler+RxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271A97421CFC99FE00D64125 /* UIViewControler+RxTests.swift */; };
3ECB51E81ECD9ADD00F8C528 /* Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ECB51E71ECD9ADD00F8C528 /* Publisher.swift */; };
3ECB51E91ECD9ADD00F8C528 /* Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ECB51E71ECD9ADD00F8C528 /* Publisher.swift */; };
3ECB51EA1ECD9ADD00F8C528 /* Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ECB51E71ECD9ADD00F8C528 /* Publisher.swift */; };
3ECB51EB1ECD9ADD00F8C528 /* Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ECB51E71ECD9ADD00F8C528 /* Publisher.swift */; };
3ECB51ED1ECD9AED00F8C528 /* EventHub.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ECB51EC1ECD9AED00F8C528 /* EventHub.swift */; };
3ECB51EE1ECD9AED00F8C528 /* EventHub.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ECB51EC1ECD9AED00F8C528 /* EventHub.swift */; };
3ECB51EF1ECD9AED00F8C528 /* EventHub.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ECB51EC1ECD9AED00F8C528 /* EventHub.swift */; };
3ECB51F01ECD9AED00F8C528 /* EventHub.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ECB51EC1ECD9AED00F8C528 /* EventHub.swift */; };
3ECB51F21ECD9AF700F8C528 /* Publisher+SharedSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ECB51F11ECD9AF700F8C528 /* Publisher+SharedSequence.swift */; };
3ECB51F31ECD9AF700F8C528 /* Publisher+SharedSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ECB51F11ECD9AF700F8C528 /* Publisher+SharedSequence.swift */; };
3ECB51F41ECD9AF700F8C528 /* Publisher+SharedSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ECB51F11ECD9AF700F8C528 /* Publisher+SharedSequence.swift */; };
3ECB51F51ECD9AF700F8C528 /* Publisher+SharedSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ECB51F11ECD9AF700F8C528 /* Publisher+SharedSequence.swift */; };
4613456F1D9A4467001ABAF2 /* UIWebView+RxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4613456E1D9A4467001ABAF2 /* UIWebView+RxTests.swift */; };
461345711D9A4543001ABAF2 /* UIWebView+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 461345701D9A4543001ABAF2 /* UIWebView+Rx.swift */; };
4613457C1D9A4AEE001ABAF2 /* RxWebViewDelegateProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4613457B1D9A4AEE001ABAF2 /* RxWebViewDelegateProxy.swift */; };
@ -74,6 +86,9 @@
91BE429C1CBF7EC000F6B062 /* UIPageControl+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91BE429B1CBF7EC000F6B062 /* UIPageControl+Rx.swift */; };
91BE429D1CBF7EC000F6B062 /* UIPageControl+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91BE429B1CBF7EC000F6B062 /* UIPageControl+Rx.swift */; };
91BE429F1CBF7F3D00F6B062 /* UIPageControl+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91BE429B1CBF7EC000F6B062 /* UIPageControl+Rx.swift */; };
9AF48B821E62DDA100B5FE01 /* PublisherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AF48B811E62DDA100B5FE01 /* PublisherTests.swift */; };
9AF48B831E62DDA100B5FE01 /* PublisherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AF48B811E62DDA100B5FE01 /* PublisherTests.swift */; };
9AF48B841E62DDA100B5FE01 /* PublisherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AF48B811E62DDA100B5FE01 /* PublisherTests.swift */; };
9BA1CBD31C0F7D550044B50A /* UIActivityIndicatorView+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BA1CBD11C0F7C0A0044B50A /* UIActivityIndicatorView+Rx.swift */; };
9BA1CBFD1C0F84A10044B50A /* UIActivityIndicatorView+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BA1CBD11C0F7C0A0044B50A /* UIActivityIndicatorView+Rx.swift */; };
9BA1CBFE1C0F84C40044B50A /* UIActivityIndicatorView+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BA1CBD11C0F7C0A0044B50A /* UIActivityIndicatorView+Rx.swift */; };
@ -1678,6 +1693,9 @@
1AF67DA51CED430100C310FA /* ReplaySubjectTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReplaySubjectTest.swift; sourceTree = "<group>"; };
271A97401CFC996B00D64125 /* UIViewController+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+Rx.swift"; sourceTree = "<group>"; };
271A97421CFC99FE00D64125 /* UIViewControler+RxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewControler+RxTests.swift"; sourceTree = "<group>"; };
3ECB51E71ECD9ADD00F8C528 /* Publisher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Publisher.swift; sourceTree = "<group>"; };
3ECB51EC1ECD9AED00F8C528 /* EventHub.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = EventHub.swift; path = EventHub/EventHub.swift; sourceTree = "<group>"; };
3ECB51F11ECD9AF700F8C528 /* Publisher+SharedSequence.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Publisher+SharedSequence.swift"; sourceTree = "<group>"; };
4613456E1D9A4467001ABAF2 /* UIWebView+RxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIWebView+RxTests.swift"; sourceTree = "<group>"; };
461345701D9A4543001ABAF2 /* UIWebView+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIWebView+Rx.swift"; sourceTree = "<group>"; };
4613457B1D9A4AEE001ABAF2 /* RxWebViewDelegateProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxWebViewDelegateProxy.swift; sourceTree = "<group>"; };
@ -1701,6 +1719,7 @@
88D98F2D1CE7549A00D50457 /* RxTabBarDelegateProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = RxTabBarDelegateProxy.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
914FCD661CCDB82E0058B304 /* UIPageControl+RxTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIPageControl+RxTest.swift"; sourceTree = "<group>"; };
91BE429B1CBF7EC000F6B062 /* UIPageControl+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIPageControl+Rx.swift"; sourceTree = "<group>"; };
9AF48B811E62DDA100B5FE01 /* PublisherTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PublisherTests.swift; sourceTree = "<group>"; };
9BA1CBD11C0F7C0A0044B50A /* UIActivityIndicatorView+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIActivityIndicatorView+Rx.swift"; sourceTree = "<group>"; };
A111CE961B91C97C00D0DCEE /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
AAE623751C82475700FC7801 /* UIProgressView+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIProgressView+Rx.swift"; sourceTree = "<group>"; };
@ -2309,6 +2328,14 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
3E4F6D671E69752F0070B810 /* EventHub */ = {
isa = PBXGroup;
children = (
3ECB51EC1ECD9AED00F8C528 /* EventHub.swift */,
);
name = EventHub;
sourceTree = "<group>";
};
C8093C471B8A72BE0088E94D /* RxSwift */ = {
isa = PBXGroup;
children = (
@ -2661,6 +2688,7 @@
271A97421CFC99FE00D64125 /* UIViewControler+RxTests.swift */,
4613456E1D9A4467001ABAF2 /* UIWebView+RxTests.swift */,
C8A81CA51E05EAF70008DEF4 /* UIBindingObserver+Tests.swift */,
9AF48B811E62DDA100B5FE01 /* PublisherTests.swift */,
);
path = RxCocoaTests;
sourceTree = "<group>";
@ -2973,6 +3001,8 @@
C89AB1AB1DAAC3350065FBE6 /* ControlEvent.swift */,
C89AB1AC1DAAC3350065FBE6 /* ControlProperty.swift */,
C89AB1AD1DAAC3350065FBE6 /* Driver */,
3E4F6D671E69752F0070B810 /* EventHub */,
3ECB51E71ECD9ADD00F8C528 /* Publisher.swift */,
C89AB1B41DAAC3350065FBE6 /* SharedSequence */,
C89AB1BB1DAAC3350065FBE6 /* UIBindingObserver.swift */,
);
@ -2996,10 +3026,11 @@
isa = PBXGroup;
children = (
C89AB1B51DAAC3350065FBE6 /* ObservableConvertibleType+SharedSequence.swift */,
3ECB51F11ECD9AF700F8C528 /* Publisher+SharedSequence.swift */,
C89AB1B91DAAC3350065FBE6 /* SharedSequence.swift */,
C89AB1B81DAAC3350065FBE6 /* SharedSequence+Operators.swift */,
C89AB1B61DAAC3350065FBE6 /* SharedSequence+Operators+arity.swift */,
C89AB1B71DAAC3350065FBE6 /* SharedSequence+Operators+arity.tt */,
C89AB1B81DAAC3350065FBE6 /* SharedSequence+Operators.swift */,
C89AB1B91DAAC3350065FBE6 /* SharedSequence.swift */,
C89AB1BA1DAAC3350065FBE6 /* Variable+SharedSequence.swift */,
);
path = SharedSequence;
@ -3999,6 +4030,7 @@
C8D132441C42D15E00B59FFF /* SectionedViewDataSourceType.swift in Sources */,
C89AB1FA1DAAC3350065FBE6 /* Variable+SharedSequence.swift in Sources */,
84E4D3921C9AFD3400ADFDC9 /* UISearchController+Rx.swift in Sources */,
3ECB51E81ECD9ADD00F8C528 /* Publisher.swift in Sources */,
C88254341B8A752B00B02D69 /* UITableView+Rx.swift in Sources */,
C89AB1A61DAAC25A0065FBE6 /* RxCocoaObjCRuntimeError+Extensions.swift in Sources */,
C88254161B8A752B00B02D69 /* RxCollectionViewReactiveArrayDataSource.swift in Sources */,
@ -4041,6 +4073,7 @@
C88254241B8A752B00B02D69 /* RxTextViewDelegateProxy.swift in Sources */,
C89AB2401DAAC3A60065FBE6 /* _RXDelegateProxy.m in Sources */,
C89AB2061DAAC3350065FBE6 /* KVORepresentable+Swift.swift in Sources */,
3ECB51F21ECD9AF700F8C528 /* Publisher+SharedSequence.swift in Sources */,
C89AB1E21DAAC3350065FBE6 /* Variable+Driver.swift in Sources */,
C89AB1DE1DAAC3350065FBE6 /* ObservableConvertibleType+Driver.swift in Sources */,
D9080ACF1EA05AE0002B433B /* RxNavigationControllerDelegateProxy.swift in Sources */,
@ -4066,6 +4099,7 @@
4613457C1D9A4AEE001ABAF2 /* RxWebViewDelegateProxy.swift in Sources */,
C88254301B8A752B00B02D69 /* UISearchBar+Rx.swift in Sources */,
C89AB2121DAAC3350065FBE6 /* NotificationCenter+Rx.swift in Sources */,
3ECB51ED1ECD9AED00F8C528 /* EventHub.swift in Sources */,
C88254181B8A752B00B02D69 /* ItemEvents.swift in Sources */,
C89AB1731DAAC1680065FBE6 /* ControlTarget.swift in Sources */,
C882541B1B8A752B00B02D69 /* RxTableViewDataSourceType.swift in Sources */,
@ -4084,6 +4118,7 @@
C89AB1FF1DAAC3350065FBE6 /* UIBindingObserver.swift in Sources */,
C8093EE41B8A732E0088E94D /* DelegateProxyType.swift in Sources */,
C86781AB1DB823B500B2029A /* NSTextField+Rx.swift in Sources */,
3ECB51F31ECD9AF700F8C528 /* Publisher+SharedSequence.swift in Sources */,
C89AB1E31DAAC3350065FBE6 /* Variable+Driver.swift in Sources */,
C89AB1D31DAAC3350065FBE6 /* ControlProperty+Driver.swift in Sources */,
C8A81CA11E05E82C0008DEF4 /* DispatchQueue+Extensions.swift in Sources */,
@ -4117,10 +4152,12 @@
C86781A61DB823B500B2029A /* NSSlider+Rx.swift in Sources */,
C89AB2231DAAC3350065FBE6 /* URLSession+Rx.swift in Sources */,
C86781A11DB823B500B2029A /* NSImageView+Rx.swift in Sources */,
3ECB51EE1ECD9AED00F8C528 /* EventHub.swift in Sources */,
C89AB2281DAAC33F0065FBE6 /* RxCocoa.swift in Sources */,
C8D132451C42D15E00B59FFF /* SectionedViewDataSourceType.swift in Sources */,
C80D33901B91EF9E0014629D /* Observable+Bind.swift in Sources */,
C89AB1EB1DAAC3350065FBE6 /* SharedSequence+Operators+arity.swift in Sources */,
3ECB51E91ECD9ADD00F8C528 /* Publisher.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -4186,6 +4223,7 @@
914FCD671CCDB82E0058B304 /* UIPageControl+RxTest.swift in Sources */,
C8C4F1651DE9D3FB00003FA7 /* UIGestureRecognizer+RxTests.swift in Sources */,
C83509351C38706E0027C24C /* KVOObservableTests.swift in Sources */,
9AF48B821E62DDA100B5FE01 /* PublisherTests.swift in Sources */,
C89046581DC5F6F70041C7D8 /* UISearchBar+RxTests.swift in Sources */,
C85218011E33FC160015DD38 /* RecursiveLock.swift in Sources */,
C822BACA1DB4058000F98810 /* Event+Test.swift in Sources */,
@ -4411,6 +4449,7 @@
C83509D81C3875420027C24C /* SentMessageTest.swift in Sources */,
C8C4F1851DE9DF0200003FA7 /* UISlider+RxTests.swift in Sources */,
0BA9496D1E224B9C0036DD06 /* AsyncSubjectTests.swift in Sources */,
9AF48B831E62DDA100B5FE01 /* PublisherTests.swift in Sources */,
C83509F61C38755D0027C24C /* CurrentThreadSchedulerTest.swift in Sources */,
C820A9AF1EB5073E00D431BC /* Observable+FilterTests.swift in Sources */,
C820A9DF1EB50CF800D431BC /* Observable+ThrottleTests.swift in Sources */,
@ -4526,6 +4565,7 @@
C83509BE1C3875100027C24C /* DelegateProxyTest+Cocoa.swift in Sources */,
C820A9F41EB5109300D431BC /* Observable+DefaultIfEmpty.swift in Sources */,
C820AA041EB5134000D431BC /* Observable+DelaySubscriptionTests.swift in Sources */,
9AF48B841E62DDA100B5FE01 /* PublisherTests.swift in Sources */,
C8353CEB1DA19BC500BE3F5C /* TestErrors.swift in Sources */,
C8B2908B1C94D64700E923D0 /* RxTest+Controls.swift in Sources */,
C8C4F1751DE9D80A00003FA7 /* NSSlider+RxTests.swift in Sources */,
@ -5174,6 +5214,7 @@
C89AB24B1DAAC3A60065FBE6 /* _RXKVOObserver.m in Sources */,
C8F0C00A1BBBFBB9001B112F /* RxTarget.swift in Sources */,
C8F0C00B1BBBFBB9001B112F /* UITextView+Rx.swift in Sources */,
3ECB51EB1ECD9ADD00F8C528 /* Publisher.swift in Sources */,
C8F0C00C1BBBFBB9001B112F /* RxTableViewReactiveArrayDataSource.swift in Sources */,
C8F0C00D1BBBFBB9001B112F /* RxCollectionViewDataSourceProxy.swift in Sources */,
84C225A51C33F00B008724EC /* RxTextStorageDelegateProxy.swift in Sources */,
@ -5188,6 +5229,7 @@
C8F0C0161BBBFBB9001B112F /* UITableView+Rx.swift in Sources */,
C89AB1D11DAAC3350065FBE6 /* ControlEvent+Driver.swift in Sources */,
84E4D3941C9AFD3600ADFDC9 /* UISearchController+Rx.swift in Sources */,
3ECB51F01ECD9AED00F8C528 /* EventHub.swift in Sources */,
C89AB2211DAAC3350065FBE6 /* NSObject+Rx.swift in Sources */,
C8F0C0171BBBFBB9001B112F /* RxCollectionViewReactiveArrayDataSource.swift in Sources */,
844BC8B61CE4FD7500F5C7CB /* UIPickerView+Rx.swift in Sources */,
@ -5237,6 +5279,7 @@
C89AB21D1DAAC3350065FBE6 /* NSObject+Rx+RawRepresentable.swift in Sources */,
C89AB2191DAAC3350065FBE6 /* NSObject+Rx+KVORepresentable.swift in Sources */,
C89AB2531DAAC3A60065FBE6 /* _RXObjCRuntime.m in Sources */,
3ECB51F51ECD9AF700F8C528 /* Publisher+SharedSequence.swift in Sources */,
C8F0C0381BBBFBB9001B112F /* UITextField+Rx.swift in Sources */,
C89AB1F51DAAC3350065FBE6 /* SharedSequence+Operators.swift in Sources */,
C89AB1CD1DAAC3350065FBE6 /* ControlProperty.swift in Sources */,
@ -5302,10 +5345,12 @@
D203C50B1BB9C53E00D02D00 /* UIScrollView+Rx.swift in Sources */,
C89AB1E81DAAC3350065FBE6 /* ObservableConvertibleType+SharedSequence.swift in Sources */,
C89AB1A81DAAC25A0065FBE6 /* RxCocoaObjCRuntimeError+Extensions.swift in Sources */,
3ECB51F41ECD9AF700F8C528 /* Publisher+SharedSequence.swift in Sources */,
D203C50C1BB9C53E00D02D00 /* UISearchBar+Rx.swift in Sources */,
846436E51C9AF65E0035B40D /* RxSearchControllerDelegateProxy.swift in Sources */,
C89AB1751DAAC1680065FBE6 /* ControlTarget.swift in Sources */,
D203C4FB1BB9C53700D02D00 /* RxCollectionViewDelegateProxy.swift in Sources */,
3ECB51EA1ECD9ADD00F8C528 /* Publisher.swift in Sources */,
D203C5031BB9C53E00D02D00 /* UIBarButtonItem+Rx.swift in Sources */,
C89AB1EC1DAAC3350065FBE6 /* SharedSequence+Operators+arity.swift in Sources */,
D203C4FC1BB9C53700D02D00 /* RxScrollViewDelegateProxy.swift in Sources */,
@ -5341,6 +5386,7 @@
D203C50A1BB9C53E00D02D00 /* UILabel+Rx.swift in Sources */,
C89AB1FC1DAAC3350065FBE6 /* Variable+SharedSequence.swift in Sources */,
D203C4F51BB9C52900D02D00 /* ItemEvents.swift in Sources */,
3ECB51EF1ECD9AED00F8C528 /* EventHub.swift in Sources */,
C8BCD3F61C14B6D1005F1280 /* NSLayoutConstraint+Rx.swift in Sources */,
D203C4FA1BB9C53700D02D00 /* RxCollectionViewDataSourceProxy.swift in Sources */,
C89AB2141DAAC3350065FBE6 /* NotificationCenter+Rx.swift in Sources */,

View File

@ -0,0 +1,43 @@
//
// EventHub.swift
// RxCocoa
//
// Created by Krunoslav Zaher on 9/26/16.
// Copyright © 2016 Krunoslav Zaher. All rights reserved.
//
#if !RX_NO_MODULE
import RxSwift
#endif
/**
Unit that represents observable sequence with following properties:
- it never fails
- it delivers events on `MainScheduler.instance`
- all observers share sequence computation resources
- computation of elements is reference counted with respect to the number of observers
- if there are no subscribers, it will release sequence computation resources
`EventHub<Element>` can be considered a builder pattern for observable sequences that model imperative events part of the application.
To find out more about units and how to use them, please visit `Documentation/Units.md`.
*/
public typealias EventHub<E> = SharedSequence<PublishSharingStrategy, E>
public struct PublishSharingStrategy : SharingStrategyProtocol {
public static var scheduler: SchedulerType { return publisherObserveOnScheduler }
public static func share<E>(_ source: Observable<E>) -> Observable<E> {
return source.share()
}
}
extension SharedSequenceConvertibleType where SharingStrategy == PublishSharingStrategy {
/// Adds `asEventHub` to `SharingSequence` with `PublishSharingStrategy`.
public func asEventHub() -> EventHub<E> {
return asSharedSequence()
}
}
fileprivate var publisherObserveOnScheduler: SchedulerType = MainScheduler.instance

View File

@ -0,0 +1,42 @@
//
// Publisher.swift
// RxCocoa
//
// Created by Krunoslav Zaher on 3/28/15.
// Copyright © 2017 Krunoslav Zaher. All rights reserved.
//
import Dispatch
#if !RX_NO_MODULE
import RxSwift
#endif
/// Publisher is a wrapper for `PublishSubject`.
///
/// Unlike `PublishSubject` it can't terminate with error, and when publisher is deallocated
/// it will complete it's observable sequence (`asObservable`).
public final class Publisher<Element> {
public typealias E = Element
public typealias SharingStrategy = PublishSharingStrategy
private let _subject: PublishSubject<Element>
public func publish(_ event: E) {
_subject.onNext(event)
}
/// Initializes variable with initial value.
public init() {
_subject = PublishSubject()
}
/// - returns: Canonical interface for push style sequence
public func asObservable() -> Observable<E> {
return _subject
}
deinit {
_subject.on(.completed)
}
}

View File

@ -0,0 +1,23 @@
//
// Publisher+SharedSequence.swift
// RxCocoa
//
// Created by Krunoslav Zaher on 12/28/15.
// Copyright © 2017 Krunoslav Zaher. All rights reserved.
//
#if !RX_NO_MODULE
import RxSwift
#endif
extension Publisher : SharedSequenceConvertibleType {
/// Converts `Publisher` to `SharedSequence`.
///
/// - returns: Observable sequence.
public func asSharedSequence() -> SharedSequence<PublishSharingStrategy, Element> {
let source = self.asObservable()
.observeOn(SharingStrategy.scheduler)
return SharedSequence(source)
}
}

View File

@ -0,0 +1 @@
../../RxCocoa/Traits/EventHub/EventHub.swift

View File

@ -0,0 +1 @@
../../RxCocoa/Traits/SharedSequence/Publisher+SharedSequence.swift

View File

@ -0,0 +1 @@
../../RxCocoa/Traits/Publisher.swift

View File

@ -0,0 +1,147 @@
//
// PublisherTests.swift
// Tests
//
// Created by Krunoslav Zaher on 2/26/17.
// Copyright © 2017 Krunoslav Zaher. All rights reserved.
//
import Dispatch
import RxSwift
import RxCocoa
import XCTest
import RxTest
class PublisherTest: RxTest {}
extension PublisherTest {
func testPublisherSharing() {
let scheduler = TestScheduler(initialClock: 0)
let observer1 = scheduler.createObserver(Int.self)
let observer2 = scheduler.createObserver(Int.self)
let observer3 = scheduler.createObserver(Int.self)
var disposable1: Disposable!
var disposable2: Disposable!
var disposable3: Disposable!
let publisher = Publisher<Int>()
scheduler.scheduleAt(100) { publisher.publish(0) }
scheduler.scheduleAt(210) { publisher.publish(1) }
scheduler.scheduleAt(225) { publisher.publish(2) }
scheduler.scheduleAt(245) { publisher.publish(3) }
scheduler.scheduleAt(265) { publisher.publish(4) }
scheduler.scheduleAt(200) {
disposable1 = publisher.asObservable().subscribe(observer1)
}
scheduler.scheduleAt(220) {
disposable2 = publisher.asObservable().subscribe(observer2)
}
scheduler.scheduleAt(235) {
disposable1.dispose()
}
scheduler.scheduleAt(260) {
disposable2.dispose()
}
// resubscription
scheduler.scheduleAt(260) {
disposable3 = publisher.asObservable().subscribe(observer3)
}
scheduler.scheduleAt(285) {
disposable3.dispose()
}
scheduler.start()
XCTAssertEqual(observer1.events, [
next(210, 1),
next(225, 2)
])
XCTAssertEqual(observer2.events, [
next(225, 2),
next(245, 3)
])
XCTAssertEqual(observer3.events, [
next(265, 4)
])
}
}
extension PublisherTest {
func testEventHubAlwaysObservingOnMainThread() {
var observedOnMainQueue = false
let expectSubscribeOffMainQueue = expectation(description: "Did subscribe off main thread")
let publisher = Publisher<Int>()
_ = publisher.asEventHub().asObservable().subscribe(onNext: { value in
XCTAssertTrue(DispatchQueue.isMain)
observedOnMainQueue = true
XCTAssertEqual(value, 1)
})
doOnBackgroundQueue {
let d = publisher.asObservable().subscribe { n in
}
let d2 = publisher.asObservable().subscribe { n in
}
doOnMainQueue {
d.dispose()
d2.dispose()
expectSubscribeOffMainQueue.fulfill()
}
}
publisher.publish(1)
waitForExpectations(timeout: 1.0) { error in
XCTAssertNil(error)
}
XCTAssertTrue(observedOnMainQueue)
}
}
// MARK: map
extension PublisherTest {
func testPublisherMap() {
let publisher = Publisher<Int>()
let observer = PrimitiveMockObserver<Int>()
let _ = publisher.asEventHub().map { $0 + 1 }.asObservable().subscribe(observer)
publisher.publish(0)
XCTAssertEqual(observer.events, [next(1)])
}
}
// MARK: combine with Driver Sequence
extension PublisherTest {
func testEventHubIsDriverCombinable() {
let publisher = Publisher<Void>()
let driver = Driver.just(1)
let exp = expectation(description: "With latest from driver")
_ = publisher.asEventHub().map { $0 }.withLatestFrom(driver).asDriver(onErrorJustReturn: 0).drive(onNext: { value in
XCTAssertEqual(value, 1)
exp.fulfill()
})
publisher.publish()
waitForExpectations(timeout: 0.3, handler: nil)
}
}