Compare commits

...

509 Commits

Author SHA1 Message Date
Stanislav Kaluzhnyi 8b07d0cbde Collection view's reload data has been changed to reload sections 2016-09-07 17:22:52 +04:00
Krunoslav Zaher 2969fbe70d Fixes for issue template. 2016-08-27 12:45:03 +02:00
Krunoslav Zaher 6ed8c6c00d Updates issue template. 2016-08-27 12:41:04 +02:00
Krunoslav Zaher de28113c06 Updates README.md with Swift 2.3 version. 2016-08-27 12:33:10 +02:00
Krunoslav Zaher 08501da396 Merge pull request #848 from damianesteban/fix/readme-carthage-directions
Fix carthage directions in readme
2016-08-25 18:16:48 +02:00
Damian Esteban e85b3203bc Fix carthage directions in readme 2016-08-25 12:08:43 -04:00
Krunoslav Zaher 900035d78b Fixes deprecated warnings. 2016-08-21 19:26:15 +02:00
Krunoslav Zaher ef71ba9f20 Updates requirements section in README.md 2016-08-21 18:45:44 +02:00
Krunoslav Zaher 72122e3e43 Updates documentation for 3.0.0.alpha.1 2016-08-21 18:40:08 +02:00
Krunoslav Zaher 87b792e54d Adds 3.0.0.alpha.1 changes to CHANGELOG. 2016-08-21 17:17:35 +02:00
Krunoslav Zaher 8cebcd786f Excludes table and collection view deprecated APIs from watchOS. 2016-08-21 15:20:57 +02:00
Krunoslav Zaher 7208a8d1cc Improves deprecation messages for table and collection views. #841 2016-08-21 15:09:14 +02:00
Krunoslav Zaher e1f72cb566 Improves version detection. 2016-08-21 03:49:56 +02:00
Krunoslav Zaher 154ac2583d Release 3.0.0.alpha.1 2016-08-21 03:44:23 +02:00
Krunoslav Zaher 136322ab6a Moves OSX example app to top of validate script. 2016-08-21 03:41:44 +02:00
Krunoslav Zaher 24c4587b51 Fixes playgrounds. 2016-08-21 03:27:07 +02:00
Krunoslav Zaher 22219781a5 Adds skip UI tests flag. 2016-08-21 02:09:40 +02:00
Krunoslav Zaher 48bb9fcba5 Adds skip automation flags. 2016-08-21 02:06:40 +02:00
Krunoslav Zaher 7f43e1eecd Temporary disables example failing tests. ¯\_(ツ)_/¯ 2016-08-21 00:24:15 +02:00
Krunoslav Zaher f8d8c45f10 Sprinkles of workarounds for Apple bugs. 2016-08-20 23:25:49 +02:00
Krunoslav Zaher 92d4bdf5e1 Changes order of pre-release tests. 2016-08-20 23:06:30 +02:00
Krunoslav Zaher ff6e4fd651 Removes old automation tests. 2016-08-20 23:02:59 +02:00
Krunoslav Zaher b68fc4260e Adds UITests. 2016-08-20 22:59:34 +02:00
Krunoslav Zaher c9742e51b6 Removes Float80 extensions. 2016-08-20 03:13:41 +02:00
Krunoslav Zaher 1f363cea2e Updates project signing. 2016-08-20 03:12:59 +02:00
Krunoslav Zaher 83f3323ed8 Sets validation to use custom CocoaPods build. 2016-08-20 02:58:18 +02:00
Krunoslav Zaher 278c681753 Fixes UICollectionView deprecation warning. 2016-08-19 15:57:46 +02:00
Krunoslav Zaher 9b1f22e6a0 Fixes deprecated rename for `NopDisposable`. 2016-08-19 15:34:22 +02:00
Krunoslav Zaher 9473953b65 Fixes compilation issues with RxExample-iOS tests. 2016-08-19 02:05:41 +02:00
Krunoslav Zaher 1998e54085 Fixes RxCocoa compilation issues. 2016-08-19 01:59:06 +02:00
Krunoslav Zaher 94d6c01e3b Enables testability. 2016-08-19 01:49:57 +02:00
Krunoslav Zaher a4f15128bf Deprecates `RxTextInput` in favor of `TextInput`. 2016-08-19 01:46:27 +02:00
Krunoslav Zaher 5610073ca9 Adds comments to `Reactive`. 2016-08-19 01:46:09 +02:00
Krunoslav Zaher 9ce054936d Merge branch 'swift-3.0-removing-rx_-prefix' of https://github.com/JegnuX/RxSwift into JegnuX-swift-3.0-removing-rx_-prefix 2016-08-19 00:45:51 +02:00
Krunoslav Zaher 4bd842301b Merge pull request #835 from mohsenr/xcode8-beta6
[Swift 3.0] Fixes for Xcode8 beta6
2016-08-18 00:14:51 +02:00
Mo Ramezanpoor 0fe4c9a792 Fixes RxExample. 2016-08-17 09:49:29 +01:00
Mo Ramezanpoor b9b593d740 Adds a nullability annotation to `_RXDelegateProxy`.
`AllTests` now passes.
2016-08-17 09:28:56 +01:00
Krunoslav Zaher 6763f1a4b7 Replaces `open` with `public`. 2016-08-16 22:10:41 +02:00
Mo Ramezanpoor d43e717415 WIP: AllTests compiles. 2016-08-16 16:09:08 +01:00
Mo Ramezanpoor 819635d9aa Fixes RxTests. 2016-08-16 15:36:44 +01:00
Mo Ramezanpoor b0026d65eb Fixes RxCocoa for macOS. 2016-08-16 15:36:20 +01:00
Mo Ramezanpoor 695ea19e02 WIP: Fixes warnings in RxCocoa. 2016-08-16 15:31:51 +01:00
Mo Ramezanpoor e55c6675f4 Removes the KVOCallback type alias.
The compiler wouldn’t recognise that it should be imported as escaping.
2016-08-16 15:13:47 +01:00
Mo Ramezanpoor 301ad9f438 WIP: Fix a bunch of RxCocoa compilation issues. 2016-08-16 15:01:07 +01:00
Mo Ramezanpoor 047c77a698 WIP: Removes a call to `unsafeAddress(of:)`. 2016-08-16 14:28:35 +01:00
Mo Ramezanpoor a2be331fee WIP: Fixes signature of `ReplaySubject.create()`. 2016-08-16 14:25:57 +01:00
Mo Ramezanpoor 2d36297601 WIP: Marks escaping closures as such. 2016-08-16 14:25:15 +01:00
Mo Ramezanpoor c12b315149 WIP: Fixes private access issues. 2016-08-16 14:25:01 +01:00
Mo Ramezanpoor 74464a4940 WIP: Clarifies references to `Swift.Never`. 2016-08-16 14:01:52 +01:00
Mo Ramezanpoor fcf8e4d092 WIP: Updates code for Xcode 8 beta 6 using the migrator with manual auditing.
The code doesn’t compile yet.
2016-08-16 14:00:14 +01:00
Jérôme Alves 43c0b952ec Remove `AnyObject` constraint and add a new protocol `ReactiveCompatible` to mark types which should be extended with the `rx` var. 2016-08-16 10:47:26 +02:00
Jérôme Alves 96ef70cc2f Update documentation (.md files) 2016-08-16 09:05:24 +02:00
Krunoslav Zaher 7adc86f7d2 Adds `onSubscribe` and `onDispose` for `do` operator. #583 2016-08-16 00:03:30 +02:00
Jérôme Alves cbb0ed5d29 Merge branch 'swift-3.0' into swift-3.0-removing-rx_-prefix 2016-08-15 19:19:22 +02:00
Krunoslav Zaher e2f4bad2bb Merge pull request #831 from JegnuX/swift-3.0-type-fix
[Swift 3.0] Fix ActivityToken dispose type.
2016-08-15 18:57:08 +02:00
Jérôme Alves 7f65914f93 Fix ActivityToken dispose type. 2016-08-15 17:53:13 +02:00
Jérôme Alves e59adc3ae9 Updates Unit Tests and makes them succeed. 2016-08-15 17:46:13 +02:00
Jérôme Alves e4e422c4f1 Merge branch 'swift-3.0' into swift-3.0-removing-rx_-prefix
Conflicts:
	RxCocoa/Common/Observables/NSNotificationCenter+Rx.swift
	RxCocoa/OSX/NSImageView+Rx.swift
	RxCocoa/iOS/UICollectionView+Rx.swift
	RxCocoa/iOS/UIControl+Rx.swift
	RxCocoa/iOS/UIImageView+Rx.swift
	RxCocoa/iOS/UILabel+Rx.swift
	RxCocoa/iOS/UITableView+Rx.swift
	RxExample/RxDataSources/DataSources+Rx/UISectionedViewType+RxAnimatedDataSource.swift
	RxExample/RxExample/Examples/APIWrappers/APIWrappersViewController.swift
	RxExample/RxExample/Examples/GitHubSearchRepositories/GitHubSearchRepositoriesViewController.swift
	RxExample/RxExample/Examples/GitHubSignup/UsingDriver/GitHubSignupViewController2.swift
	RxExample/RxExample/Examples/GitHubSignup/UsingVanillaObservables/GitHubSignupViewController1.swift
	RxExample/RxExample/Examples/ImagePicker/UIImagePickerController+RxCreate.swift
	RxExample/RxExample/Examples/OSX simple example/IntroductionExampleViewController.swift
	RxExample/RxExample/Examples/SimpleTableViewExample/SimpleTableViewExampleViewController.swift
	RxExample/RxExample/Examples/SimpleTableViewExampleSectioned/SimpleTableViewExampleSectionedViewController.swift
	RxExample/RxExample/Examples/SimpleValidation/SimpleValidationViewController.swift
	RxExample/RxExample/Examples/TableViewPartialUpdates/PartialUpdatesViewController.swift
	RxExample/RxExample/Examples/TableViewWithEditingCommands/TableViewWithEditingCommandsViewController.swift
	RxExample/RxExample/Examples/WikipediaImageSearch/Views/WikipediaSearchCell.swift
	RxExample/RxExample/Examples/WikipediaImageSearch/Views/WikipediaSearchViewController.swift
	Tests/RxCocoaTests/DelegateProxyTest.swift
	Tests/RxCocoaTests/KVOObservableTests.swift
	Tests/RxCocoaTests/RxTest+Controls.swift
	Tests/RxCocoaTests/UICollectionView+RxTests.swift
	Tests/RxCocoaTests/UIScrollView+RxTests.swift
	Tests/RxCocoaTests/UITableView+RxTests.swift
2016-08-15 12:17:26 +02:00
Krunoslav Zaher 4f54c9bf5a Merge branch 'swift-3.0' of github.com:kzaher/RxSwift into swift-3.0 2016-08-15 01:12:21 +02:00
Krunoslav Zaher 8b00921da7 Merge branch 'develop' into swift-3.0 2016-08-15 01:08:36 +02:00
Krunoslav Zaher bdbcb5bc87 Improves UITableView and UICollection view bindings behavior. 2016-08-14 23:25:54 +02:00
Krunoslav Zaher 55f4bb3b65 Merge pull request #828 from mohsenr/swift-3.0-disposables-rebased
[Swift 3.0] Collect all immutable Disposable constructors in `Disposables` type
2016-08-10 23:06:45 +02:00
Mo Ramezanpoor f1b4e0f6b7 Merge with 'swift-3.0' 2016-08-10 15:24:27 +01:00
Mo Ramezanpoor f8a11aa0cb Document `Disposables`. 2016-08-10 15:16:58 +01:00
Mo Ramezanpoor 8754166f35 Hides `Disposables.init()` internally by making it private. 2016-08-10 15:03:52 +01:00
Mo Ramezanpoor 75971c61c6 Replaces all calls to `AnonymousDisposable.init()` with `Disposables.create()`. 2016-08-10 15:00:29 +01:00
Mo Ramezanpoor c643d4c0b5 Returns `Cancelable` instead of `Disposable` from all overloads of `Disposables.create()` except for no-op (which is stateless). 2016-08-10 15:00:02 +01:00
Mo Ramezanpoor 64526c8dcd Replaces all calls to `StableCompositeDisposable.create()` with `Disposables.create()`. 2016-08-10 14:49:21 +01:00
Mo Ramezanpoor 1fe15bb9da Replaces all calls to `NopDisposable.instance` with `Disposables.create()`. 2016-08-10 14:47:53 +01:00
Mo Ramezanpoor a981d4caab Overloads `Disposables.create()` with a version accepting variadics after the third argument. 2016-08-10 14:43:51 +01:00
Mo Ramezanpoor 6d17e711ab Changes implementation of two overloads of `Disposables.create()` to avoid deprecation warnings. 2016-08-10 14:33:39 +01:00
Mo Ramezanpoor 341ef8fc3b Rename `Disposables.empty()` to `.create()`. 2016-08-10 14:28:13 +01:00
Mo Ramezanpoor 2812da1f5e Replace immutable initialisations of `CompositeDisposable` with `Disposables.create()`.
The factory methods will select specialised implementations based on the case.
2016-08-10 14:27:45 +01:00
Krunoslav Zaher 2498b3194d Merge pull request #829 from rhx/swift-3.0
Update for Xcode 8 beta 5
2016-08-10 15:04:12 +02:00
Rene Hexel 2e4b6990e8 Update for Xcode 8 beta 5 2016-08-10 09:45:23 +10:00
Krunoslav Zaher 6eda820476 Merge pull request #827 from mohsenr/swift-3.0-isDisposed
[Swift 3.0] Renames `disposed` to `isDisposed`
2016-08-09 21:34:53 +02:00
Mo Ramezanpoor 2df8c43077 Deprecates `StableCompositeDisposable.create()` in favour of `Disposables.create()`. 2016-08-09 10:45:29 +01:00
Mo Ramezanpoor ac876f35db Deprecates `AnonymousDisposable.init` in favour of `Disposables.create()`. 2016-08-09 10:34:43 +01:00
Mo Ramezanpoor 0058d2ff67 Deprecates `NopDisposable.instance` in favour of `Disposables.empty()`. 2016-08-09 10:32:35 +01:00
Mo Ramezanpoor 23ae9692e7 Change Disposables.empty from a property to a method to mirror `Observable.empty()`. 2016-08-09 10:30:18 +01:00
Mo Ramezanpoor eb646a97a6 Makes `BinaryDisposable` private.
Uses `Disposables.create()` instead.
2016-08-09 10:24:02 +01:00
Mo Ramezanpoor b0a819981b Implement `Cancelable.disposed` as an extension. 2016-08-09 10:12:55 +01:00
Mo Ramezanpoor d3eacdfcb5 BinaryDisposable is no longer public. 2016-08-09 10:05:49 +01:00
Mo Ramezanpoor dbc635d6e7 Create Disposables type. 2016-08-09 09:55:11 +01:00
Mo Ramezanpoor cb5d23c757 Removes defunct NAryDisposable.(swift|tt) files. 2016-08-09 09:54:39 +01:00
Mo Ramezanpoor 38e5a500c7 Makes some disposable classes marked as final. 2016-08-09 09:54:20 +01:00
Mo Ramezanpoor 6887745089 Renames `MySubject.diposed` (with a typo) to `.isDisposed`. 2016-08-09 09:50:36 +01:00
Mo Ramezanpoor e530858bd0 Renames `disposed` to `isDisposed` in any place that it makes semantically. 2016-08-09 09:50:13 +01:00
Jérôme Alves 10ff55cfba Moves RxCocoa extensions from `rx_` syntax to `rx.` syntax.
The main work is done in this commit but the feature it's still "work in progress"
2016-08-09 00:17:38 +02:00
Krunoslav Zaher 46286d3291 Bumps up podspec OSX minimal version to 10.10. #791 2016-08-07 20:27:31 +02:00
Krunoslav Zaher aef4e69339 Modernizes APIs. 2016-08-07 20:14:19 +02:00
Krunoslav Zaher 3637153169 Fixes warnings. 2016-08-07 18:59:36 +02:00
Krunoslav Zaher 8a58deaa2b Deprecates `toObservable` in favor of `from` operator. 2016-08-07 18:54:23 +02:00
Krunoslav Zaher 441a4a22db Modernizes doOn operator. 2016-08-07 18:24:33 +02:00
Krunoslav Zaher d1cde77b18 Modernizes image view extensions. 2016-08-07 18:08:13 +02:00
Krunoslav Zaher afd40f5d8b Modernizes UICollectionView extensions. 2016-08-07 16:48:25 +02:00
Krunoslav Zaher 1b0e0a3c88 Updates RxDataSources. 2016-08-07 16:12:16 +02:00
Krunoslav Zaher 10b0d39e05 Fixes warnings. 2016-08-07 16:04:47 +02:00
Krunoslav Zaher 091b12242a Merge branch 'master' into swift-3.0 2016-08-07 15:28:44 +02:00
Krunoslav Zaher 4b602fd88e Merge remote-tracking branch 'origin/master' into develop 2016-08-07 15:27:58 +02:00
Krunoslav Zaher 2f06600985 Merge pull request #823 from vburojevic/typos
Typo in Getting Started
2016-08-07 15:27:31 +02:00
Krunoslav Zaher 8e01b2ffe4 Merge pull request #820 from tqtifnypmb/master
Typo
2016-08-07 15:27:09 +02:00
Krunoslav Zaher 9c14b7fde1 Merge pull request #824 from ReactiveX/slack-channel-url
Update README.md
2016-08-07 15:26:59 +02:00
Krunoslav Zaher 03d6950bf1 Merge branch 'develop' into swift-3.0 2016-08-07 15:24:44 +02:00
Krunoslav Zaher 7b6a244f45 Fixes problem with data sources. 2016-08-07 15:23:17 +02:00
Krunoslav Zaher e2c3330d61 Fixes default datasources implementation. #825 2016-08-07 15:12:54 +02:00
Junior B 208a84db0f Update README.md 2016-08-07 01:33:37 +02:00
Vedran Burojević 0b1856d43e Fixes typo in Getting Started 2016-08-06 19:44:02 +02:00
Krunoslav Zaher 58e427b045 Fixes playgrounds compilation issues. 2016-08-04 11:53:19 +02:00
Krunoslav Zaher a2ee04e721 Fixes unit tests. 2016-08-04 11:12:53 +02:00
Krunoslav Zaher 38c45c066d Example compilation fixes. 2016-08-04 10:56:09 +02:00
Krunoslav Zaher 01d86ff684 Fixes OSX compilation issues. 2016-08-04 10:48:36 +02:00
Krunoslav Zaher 2ead37809e Fixes example app compiling. 2016-08-04 10:44:46 +02:00
LZL 72e5488631 Typo 2016-08-03 17:27:15 +08:00
Krunoslav Zaher 21a56a8ebd Fixes all tests. 2016-08-02 14:51:04 +02:00
Yuki Nagai a9d0cfeb5b Add Error extension instead of NSError for Workaround; NSError extension returns a type which conforms to Error protocol 2016-08-02 21:48:01 +09:00
Yuki Nagai 7f84ec604e WIP. Update for Xcode 8 beta 4. 2016-08-02 15:46:11 +09:00
Krunoslav Zaher bfb9441414 Merge pull request #812 from nishitaniyuki/fix-minor-typo
Fix minor typo
2016-08-01 11:47:28 +02:00
Krunoslav Zaher 3b34850675 Merge branch 'swift-3.0' of github.com:kzaher/RxSwift into swift-3.0 2016-08-01 10:47:06 +02:00
Krunoslav Zaher c844b6bdb3 Merge branch 'develop' into swift-3.0 2016-08-01 10:46:20 +02:00
Krunoslav Zaher dffd6f0e1c Moves playgrounds from workspace to project. #806 2016-08-01 10:27:18 +02:00
nishitani yuki 544e00d917 Fix minor typo 2016-08-01 13:52:57 +09:00
Krunoslav Zaher 490b6cbbc5 Merge pull request #790 from sunshinejr/swift-3.0
[Swift 3.0] Remove first parameter names for Observables.
2016-07-29 12:11:35 +02:00
Krunoslav Zaher b1c6673da7 Merge pull request #801 from mohsenr/swift-3.0-disposables
[Swift 3.0] Rename disposable-related methods (implements #800)
2016-07-28 23:49:17 +02:00
Krunoslav Zaher 372d766519 Merge pull request #809 from peagasilva/patch-1
Update Rx.playground/Pages/Introduction/Contents.swift
2016-07-28 23:46:24 +02:00
Raphael Silva 40eb452040 Update Contents.swift
Typo fixed - it was missing the `ed` in called.
2016-07-28 18:06:29 -03:00
Mo Ramezanpoor 99e21bdb46 Rename CompositeDisposable.removeDisposable(forKey:) to .remove(for:).
Decided as part of #800 that this is more suitable.
2016-07-27 16:34:38 +01:00
Krunoslav Zaher d12b8321d2 Merge pull request #804 from devxoul/tableview-willdisplaycell
Fix type mismatch in UITableView.rx_willDisplayCell
2016-07-27 16:00:19 +02:00
Suyeol Jeon f303efb077 Fix type mismatch in UITableView.rx_willDisplayCell 2016-07-27 04:15:17 +09:00
Łukasz Mróz 181a94bbc9 [Swift3] doOn syntax. 2016-07-25 20:39:01 +02:00
Mo Ramezanpoor fa14592a2b Rename disposeAllIn(_:) to disposeAll(in:).
Ideally we’d move this to be a method on Bag where T: Disposable. Unfortunately atm that doesn’t work on Bag<Disposable> itself, only on concrete types inheriting from it.

We can at least make the function feel more at home in Swift 3.
2016-07-25 16:04:32 +01:00
Mo Ramezanpoor 61420eef9f Add DisposeBag.insert() and deprecate DisposeBag.addDisposable().
Update [the only] known call site to match.
2016-07-25 15:37:33 +01:00
Mo Ramezanpoor fbee131886 Update all known call sites to use the new insert/remove methods on CompositeDisposable. 2016-07-25 15:31:40 +01:00
Mo Ramezanpoor 2cb931d8e9 Add new insert/remove methods to CompositeDisposable that follow Swift 3 naming conventions. 2016-07-25 15:30:54 +01:00
Krunoslav Zaher 0c8d28b1b6 Fixes disposing for debug operator in case of termination event. 2016-07-23 16:20:10 +02:00
Krunoslav Zaher 1301e9925a Fixes for Swift 3.0 2016-07-23 16:05:04 +02:00
Krunoslav Zaher 070907471c Fixes problem with schedulers introduced with Swift 3.0 and changes in libdispatch. #799 2016-07-23 14:14:08 +02:00
Krunoslav Zaher f3f2b0e083 Updates to Swift 3.0 2016-07-22 22:34:34 +02:00
Krunoslav Zaher e79457dcd3 Fixes for Xcode beta 3. 2016-07-20 22:14:59 +02:00
Krunoslav Zaher 824f23c94e Merge pull request #797 from noremac/swift-3.0
Adds further Xcode 8 beta 3 fixes.
2016-07-20 01:10:29 +02:00
Cameron Pulsford 5c908f18b8 Adds further Xcode 8 beta 3 fixes. 2016-07-19 18:42:18 -04:00
Krunoslav Zaher d4981303b5 Merge pull request #796 from noremac/swift-3.0
Updates project with Xcode 8 beta 3.
2016-07-20 00:04:17 +02:00
Cameron Pulsford 7c2f20cf36 Updates project with Xcode 8 beta 3. 2016-07-19 11:33:06 -04:00
Krunoslav Zaher cba021a961 Adds `swift-3.0` as valid branch in Dangerfile. 2016-07-11 01:36:22 +02:00
Krunoslav Zaher 9cac0cc234 Adaptations for Swift 3.0. 2016-07-10 14:55:18 +02:00
Krunoslav Zaher b47ce13eae Adds printing of environment info. 2016-07-10 13:06:00 +02:00
Krunoslav Zaher 1124f40ef1 Fixes Swift version. 2016-07-10 12:45:41 +02:00
Krunoslav Zaher 03fae9de6f Changes deployment target for example app. 2016-07-10 12:39:02 +02:00
Krunoslav Zaher 996caf6917 Fixes platform. 2016-07-10 12:33:55 +02:00
Krunoslav Zaher a1b34f0f50 Fixes unit tests warning. 2016-07-10 12:29:29 +02:00
Krunoslav Zaher 125deae0c8 Fixes tvOS compilation. 2016-07-10 12:23:50 +02:00
Krunoslav Zaher 8e46d377da Fixes concurrent dispatch queue scheduler initializer. 2016-07-10 12:18:11 +02:00
Krunoslav Zaher 348ce89e17 Fixes `rx_sentMessage` unit tests. 2016-07-10 11:33:51 +02:00
Krunoslav Zaher e222e52223 Deletes RxExample-iOS-no-module scheme. 2016-07-09 23:11:54 +02:00
Krunoslav Zaher edf423d42e Improves KVOObservable code. 2016-07-08 00:20:24 +02:00
Krunoslav Zaher e2edffc39d Fixes `@warn_unused_result(message: "http://git.io/rxs.ud")` warnings. 2016-07-08 00:04:44 +02:00
Krunoslav Zaher 6770c8a4c0 Fixes `.self` warnings. 2016-07-08 00:02:45 +02:00
Krunoslav Zaher bce8e9cd2d Fixes example app. 2016-07-07 23:50:38 +02:00
Krunoslav Zaher a64c07d1e1 Merge pull request #787 from sergdort/swift-3.0
Merged latest master
2016-07-07 23:22:57 +02:00
Krunoslav Zaher 7cc3dab5cb Merge pull request #789 from kciter/remove-meaningless-line
Remove typealias Parent line in Filter.swift
2016-07-07 21:50:39 +02:00
Lee Sun-Hyoup 6757b82872 Remove typealias Parent line in Filter.swift 2016-07-07 18:53:59 +09:00
sergdort d40557bbd7 Fixed test failing on `testObservingForAllTypes` 2016-07-07 10:29:04 +03:00
Krunoslav Zaher 987afd4a92 Merge pull request #786 from mohsenr/swift-3.0
Update for Xcode 8 beta 2.
2016-07-07 00:21:55 +02:00
Mo Ramezanpoor 14fa47c623 Update for Xcode 8 beta 2.
`Thread.current` is a class property, not a method.
2016-07-06 11:34:49 +01:00
sergdort 7e2a492895 Fixed the bug with determining property attributes in KVOObservable 2016-07-06 10:29:38 +03:00
sergdort b7cd7ba56c Fixes after merge conflicts 2016-07-05 18:07:18 +03:00
sergdort cfb8b1558a Merge branch 'master' into swift-3.0
Conflicts:
	RxExample/RxDataSources/DataSources/CollectionViewSectionedDataSource.swift
	RxExample/RxDataSources/DataSources/Differentiator.swift
	RxExample/RxDataSources/DataSources/TableViewSectionedDataSource.swift
	RxExample/RxExample.xcodeproj/project.pbxproj
	RxExample/RxExample.xcodeproj/xcshareddata/xcschemes/RxExample-iOS-no-module.xcscheme
	RxExample/RxExample/Examples/TableViewPartialUpdates/PartialUpdatesViewController.swift
	RxExample/RxExample/Examples/TableViewWithEditingCommands/TableViewWithEditingCommandsViewController.swift
	RxExample/RxExample/Services/HtmlParsing.swift
	Tests/RxCocoaTests/CLLocationManager+RxTests.swift
	Tests/RxCocoaTests/UICollectionView+RxTests.swift
2016-07-05 18:00:36 +03:00
Krunoslav Zaher 95ee9d0de8 Fixes problem with editing UITableView example. #768 2016-07-04 20:55:54 +02:00
Krunoslav Zaher ca831c7321 Updates README with a friendly information about Xcode 8.0 beta. 2016-07-04 07:16:33 +02:00
Krunoslav Zaher 56e09abb11 Fixes problem with Swift 2.3 2016-07-04 07:02:49 +02:00
Krunoslav Zaher 1633a4192e Disables bitcode for RxTests/tvOS because Carthage with Swift 2.3 and Xcode 8.0 fails to compile it. 2016-07-04 06:13:58 +02:00
Krunoslav Zaher f51151c3d2 Fixes RandomAPI response Parsing. 2016-07-04 04:25:21 +02:00
Krunoslav Zaher 2787393621 Fixes for Xcode 7.3.1 2016-07-04 04:06:01 +02:00
Krunoslav Zaher 5c0ce0a1c8 Xcode 8 beta, Swift 2.3 fixes. 2016-07-04 03:35:41 +02:00
Krunoslav Zaher bce72a2617 Fixes headers. 2016-07-04 02:54:32 +02:00
Krunoslav Zaher 68b5ae3e4c Xcode 8.0 fixes. 2016-07-04 02:48:41 +02:00
Krunoslav Zaher f86d12a53b Release 2.6.0 2016-07-04 02:27:30 +02:00
Krunoslav Zaher 88f718ffc3 Updates latest version of data sources. 2016-07-04 02:06:08 +02:00
Krunoslav Zaher e20ac5fbb7 Adds simple data source usage examples in inline docs. 2016-07-04 01:42:26 +02:00
Krunoslav Zaher 2d50bc135c Fixes compilation for Swift 2.3 compiler. 2016-07-04 01:07:19 +02:00
Krunoslav Zaher 17f8aac437 Removes unit tests failing because of accidentally included plist. 2016-07-04 01:03:13 +02:00
Krunoslav Zaher f95b1ed122 Unit tests, documents and improves data source/delegate interfaces. 2016-07-04 01:02:08 +02:00
Krunoslav Zaher 7e17ca9fde Updates mdast to remark. 2016-07-03 22:03:26 +02:00
Krunoslav Zaher 6b031f97bd Merge branch 'develop' of github.com:ReactiveX/RxSwift into develop 2016-07-03 16:37:32 +02:00
Krunoslav Zaher c0939e1b4e Removes RxExample-no-module scheme. 2016-07-03 16:05:46 +02:00
Krunoslav Zaher e3d2305a8f Fixes building playgrounds. 2016-07-03 13:03:47 +02:00
Krunoslav Zaher 5b95007fba Merge pull request #778 from sunshinejr/feature/equatable_recorded_public
[RxTests] Make equatable operator for Recorded public.
2016-07-03 13:03:09 +02:00
Krunoslav Zaher d1916b4a19 Merge pull request #779 from tomburns/fix-rxblocking
Fix RxBlocking in Swift 3
2016-07-03 13:00:57 +02:00
Tom Burns 98cf430382 Fix ConcurrentDispatchQueueSchd's schedulePeriodic
Fix interval conversion error (new API expects Double, not TimeInterval)
2016-07-02 19:58:29 -05:00
Tom Burns c33d5806fd Remove errant whitespace 2016-07-02 18:47:47 -05:00
Tom Burns 45b8b32b35 Fix RxBlocking in Swift 3
Remove force cast in favor of rawValue to fix crash at runtime
2016-07-02 18:45:08 -05:00
Łukasz Mróz 8989ea3a0a [RxTests] Make equatable Recorded public 2016-07-02 23:04:41 +02:00
Krunoslav Zaher ad96d6b0e1 Merge pull request #777 from baek-jinoo/minor-typo-fix
Minor typo fix
2016-07-01 10:42:21 +02:00
Krunoslav Zaher 5a9771e818 Removes no-module version. 2016-06-30 10:51:05 +02:00
Krunoslav Zaher 62bd1d5498 Fixes all-tests.sh 2016-06-30 10:49:07 +02:00
Krunoslav Zaher bbea37dcda Merge pull request #775 from DouglasHeriot/swift-2.3
Update for Xcode 8, Swift 2.3.
2016-06-30 10:47:47 +02:00
Krunoslav Zaher b72a2ce86d Merge pull request #776 from DouglasHeriot/swift-3.0
Make Travis use Xcode 8 for building Swift 3
2016-06-30 10:45:19 +02:00
Douglas Heriot 67160ee0dc Put Travis back to Xcode 7.3
Upgrading to 8 requires all .swift build scripts to use Swift 3, which isn't appropriate in this branch.
2016-06-30 00:41:14 +10:00
Douglas Heriot 76a63104fa Update Travis to use Xcode 8.
Also update validate-headers.swift for Swift 3.
2016-06-30 00:26:04 +10:00
Douglas Heriot 5a566ae183 Fix RxExample for Xcode 8, Swift 2.3 2016-06-29 22:54:12 +10:00
Krunoslav Zaher e730955869 Merge pull request #770 from tonyarnold/fix/static-analysis-issues
Resolve minor static analysis issues
2016-06-29 13:37:57 +02:00
Tony Arnold 1a289e97fd Add information about resolved static analysis issues in RxCocoa’s Objective-C classes to the changelog 2016-06-29 11:31:21 +10:00
Tony Arnold e4219c8423 Add RX_CATCH_ERROR macro to work around implicit nullable state of NSError parameters in Objective-C methods 2016-06-29 10:59:13 +10:00
Douglas Heriot d48dff3a4f Update for Xcode 8, Swift 2.3.
Bump OSX Deployment Target to 10.10 to avoid libarclite duplicate linking error?
2016-06-29 01:54:19 +10:00
Tony Arnold c50efe34c7 Initialise targetClass to NULL to silence a static analysis issue 2016-06-28 13:17:17 +10:00
Krunoslav Zaher 0815ea5c96 Merge pull request #767 from sora0077/feature/RXDelegateProxy_weak
Change _forwardToDelegate to weak reference
2016-06-27 17:21:24 +02:00
林達也 fc0fdb4850 Change _forwardToDelegate to weak reference 2016-06-27 23:31:38 +09:00
Krunoslav Zaher 7ec1ffc935 Merge branch 'sergdort-swift-3.0' into swift-3.0 2016-06-26 15:28:35 +02:00
Krunoslav Zaher 7089f6d7de Fixes .travis.yml 2016-06-26 15:03:24 +02:00
Krunoslav Zaher f72cc12b94 Improves CONTRIBUTING.md 2016-06-26 14:59:45 +02:00
Krunoslav Zaher 37560a734e Moves issue template to root. 2016-06-26 14:53:12 +02:00
Krunoslav Zaher 933cb02cb0 Adds `UIButton.setTitle` extensions to tvOS. 2016-06-26 14:37:10 +02:00
sergdort ada55ed8e5 Fixed compile error on all tests MAC os 2016-06-25 22:14:04 +03:00
sergdort 5bf319adda Made RxAllTests compile with Swift 3.0 2016-06-25 22:10:12 +03:00
Krunoslav Zaher 7a15347943 Adds UIButton.setTitle(:forState:) extensions. 2016-06-24 23:11:08 +02:00
Krunoslav Zaher c51f4f3b95 Merge branch 'jamiepinkham-swift-3.0' into swift-3.0 2016-06-23 11:06:13 +02:00
Jamie Pinkham c719c8cf86 fix compiler warnings about unused variables 2016-06-22 10:16:49 -04:00
Jamie Pinkham 5d47db7609 fix errors with RxCocoa introduced by merge 2016-06-22 10:15:37 -04:00
Jamie Pinkham 7ff150aafc clean up changes from merge 2016-06-22 10:01:59 -04:00
Jamie Pinkham 5a9f47262a Merge branch 'upstream-develop' into swift-3.0
# Conflicts:
#	RxCocoa/Common/CocoaUnits/Driver/Driver+Subscription.swift
#	RxCocoa/Common/CocoaUnits/UIBindingObserver.swift
#	RxSwift/Schedulers/MainScheduler.swift
2016-06-22 09:54:44 -04:00
Jamie Pinkham db4c04dcea use Foundation.Timer
and fix result of call unused warning
2016-06-22 09:51:01 -04:00
Jamie Pinkham 9287bebd10 fix retryWhen syntax 2016-06-22 09:37:32 -04:00
Jamie Pinkham 924a9a4983 clean up syntax to get test building
still trying to work out the ambiguious use compiler error
2016-06-22 09:34:04 -04:00
Jamie Pinkham 8d5b85306d fix up @noescape clauses 2016-06-21 08:48:45 -04:00
Jamie Pinkham bc86d47a3f swift 3.0 syntax updates for preprocessor and performance tools 2016-06-21 08:45:56 -04:00
Jamie Pinkham a5f19de922 fix reachability 2016-06-21 08:45:00 -04:00
baek-jinoo 8ce99d1219 Minor typo fix 2016-06-20 17:45:37 -07:00
Jamie Pinkham 8bad8e547f fix wireframe for mac tests 2016-06-20 14:06:36 -04:00
Jamie Pinkham ced6ce3a7e fixes the unit tests for the rx ios example 2016-06-20 14:04:42 -04:00
Jamie Pinkham ff0d588189 fix what tests i can 2016-06-18 15:43:27 -07:00
Jamie Pinkham c35136fe0b get example projects working.. woo! 2016-06-18 15:21:44 -07:00
Jamie Pinkham 39a20441e1 begin fixing up the examples 2016-06-18 01:24:07 -07:00
Jamie Pinkham c4cf2e0d12 builds ios, ios rx cocoa and ios rx blocking 2016-06-17 23:19:16 -07:00
Jamie Pinkham 0e38ecbc87 Merge branch 'develop' into swift-3.0
# Conflicts:
#	Documentation/DesignRationale.md
#	Rx.playground/Pages/Introduction.xcplaygroundpage/Contents.swift
#	RxCocoa/Common/DelegateProxyType.swift
#	RxCocoa/iOS/UICollectionView+Rx.swift
#	RxCocoa/iOS/UIControl+Rx.swift
#	RxCocoa/iOS/UIScrollView+Rx.swift
#	RxCocoa/iOS/UITableView+Rx.swift
#	RxExample/RxDataSources/DataSources+Rx/ObservableConvertibleType+Differentiator.swift
#	RxSwift/Concurrency/Lock.swift
#	RxSwift/Disposables/CompositeDisposable.swift
#	RxSwift/Event.swift
#	RxSwift/Extensions/String+Rx.swift
#	RxSwift/Schedulers/OperationQueueScheduler.swift
2016-06-17 21:14:06 -07:00
Krunoslav Zaher 9b1583f2e3 Merge pull request #751 from brentleyjones/swift-rand
Replace `rand` with `arc4random`
2016-06-17 12:15:28 +02:00
Brentley Jones 079ab269c0 Replace `rand` with `arc4random`
Swift 2.3 won't compile with `rand`.
2016-06-16 16:04:25 -07:00
Krunoslav Zaher 8797a05a0e Improves `drive` documentation. 2016-06-15 23:05:21 +02:00
Krunoslav Zaher 95900ef394 Merge branch 'develop' of github.com:kzaher/RxSwift into develop 2016-06-15 22:40:47 +02:00
Krunoslav Zaher 390e0d79e5 Merge pull request #742 from mattfenwick/patch-1
copy edit Schedulers.md
2016-06-14 23:58:53 +02:00
Krunoslav Zaher 087456aed3 Merge branch 'develop' of github.com:kzaher/RxSwift into develop 2016-06-14 23:46:47 +02:00
Krunoslav Zaher 96b269dc5f Documents `<->` internals better. 2016-06-14 23:44:44 +02:00
Matt Fenwick c038e7bb84 fix sentence structure 2016-06-14 10:35:36 -05:00
Matt Fenwick 9fed8676aa copy edit Schedulers.md 2016-06-14 10:14:43 -05:00
Krunoslav Zaher d59b050eda Merge pull request #738 from solidcell/update-jazzy-docs
Add a script that updates RxSwift jazzy docs
2016-06-13 14:05:00 +02:00
Krunoslav Zaher 58a66df1d9 Merge pull request #740 from ReactiveX/update-units-documentation
Remove Variable from Units documentation
2016-06-13 14:04:38 +02:00
Scott Gardner e1040cfcf8 Remove Variable from Units documentation 2016-06-10 12:01:05 -05:00
Jesse Farless 56e6d09b0f Add a script that updates RxSwift jazzy docs 2016-06-10 14:51:40 +02:00
Krunoslav Zaher 49ccdac810 Merge pull request #717 from solidcell/tab-bar-delegate-proxy
UITabBar delegate proxy
2016-06-10 11:34:40 +02:00
Krunoslav Zaher 7fbbebe404 Merge pull request #730 from solidcell/jazzy-documentation
Add API Documentation
2016-06-10 11:32:28 +02:00
Krunoslav Zaher c52090aee2 Patches the problem with <-> clearing the value on return. Correct solution is still unknown. 2016-06-10 11:26:10 +02:00
Krunoslav Zaher 49e9057d28 Merge pull request #734 from devxoul/uiscrollview-rxscrollenabled
Add UIScrollView.rx_scrollEnabled
2016-06-10 11:21:14 +02:00
Jesse Farless 34d35c1560 Update method signatures in API documentation 2016-06-10 10:36:11 +02:00
Suyeol Jeon b0bb65306b Update CHANGELOG.md 2016-06-09 00:35:37 +09:00
Krunoslav Zaher 902a659097 Changes head to base in Dangerfile. 2016-06-08 15:56:34 +02:00
Jesse Farless 6d84f30338 Unsuccessfully exit from script if jazzy gem isn't found 2016-06-08 15:49:18 +02:00
Jesse Farless 3ebb38c681 Add a .jazzy.yml file and scripts that create and update it 2016-06-08 15:19:50 +02:00
Scott Gardner ab4c845d46 Minor update to Rx.playground 2016-06-08 06:44:00 -05:00
Krunoslav Zaher b37f3f5bb6 Merge pull request #714 from bshewmak/develop
Fix Demo: Filtering and Conditional Operators
2016-06-08 13:32:44 +02:00
Krunoslav Zaher fbca0957c0 Adds warning about targetting `develop` branch to `Dangerfile`. 2016-06-08 11:51:51 +02:00
Jesse Farless 7c706713b5 Rename delegate methods to remove 'Item' suffix 2016-06-08 11:46:15 +02:00
Suyeol Jeon 0686b9a045 Add unit test for UIScrollView.rx_scrollEnabled 2016-06-08 18:31:27 +09:00
Krunoslav Zaher e464c369dc Merge pull request #725 from sergdort/danger_setup
Danger base setup
2016-06-08 11:27:40 +02:00
Krunoslav Zaher a121867280 Adds `vendor` to ignore validate headers script. 2016-06-08 10:45:14 +02:00
Krunoslav Zaher e45d3be7fd Improves header validation script. 2016-06-08 10:41:58 +02:00
Krunoslav Zaher 9e2e7abf88 Excludes `bundle` path. 2016-06-08 10:23:59 +02:00
Ben Shewmake 0514c03963 Added two additional examples to Filtering and Conditional Operators: "single with conditions".
Per suggestion by @scotteg, two additional examples were added to cover the following use cases:

* A successful matching case of exactly one element
* An error when repeated elements are observed
2016-06-07 19:42:05 -06:00
Suyeol Jeon e291bff0f0 Add UIScrollView.rx_scrollEnabled 2016-06-08 04:12:53 +09:00
sergdort e3a87c8801 Danger base setup 2016-06-03 10:27:01 +03:00
Krunoslav Zaher e26bce70af Merge branch 'master' into develop 2016-06-02 21:54:00 +02:00
Krunoslav Zaher f86e946f8f Merge pull request #724 from chunkyguy/ImproveCompileTimes
Rewrite an implementation to reduce compilation time
2016-06-02 13:33:47 +02:00
Sidharth Juyal ae9c8e3fd9 Rewrite the Bag.count implementation
This implementation is both short and fast in compilation times.
2016-06-02 11:30:56 +02:00
Krunoslav Zaher dee4a93ccb Adds test to Linux tests. 2016-05-31 21:54:57 +02:00
Krunoslav Zaher 645b93c3e4 Fixes composite disposable. 2016-05-31 21:54:35 +02:00
Krunoslav Zaher 2fdb6a6d81 Merge pull request #720 from larryonoff/feature/extend-composite-disposable
Extend CompositeDisposable with variadic init
2016-05-31 21:39:43 +02:00
Krunoslav Zaher a9fafcee41 Merge pull request #721 from kylef/kylef/rx_title
Add rx_title to UIViewController
2016-05-31 21:35:48 +02:00
Krunoslav Zaher 52c6e6dc31 Improves version checking logic. #707 2016-05-31 21:33:38 +02:00
Krunoslav Zaher 3fd15897ce Improves version checks. 2016-05-31 21:27:15 +02:00
Sidharth Juyal 00e0f5e689 Rewrite an implementation to reduce compilation time
The coalescing operator for some reasons increases the build times.
On my machine replacing the implementation brings down the compile time `Bag.count` from 1005ms to 13ms
2016-05-31 19:10:21 +02:00
Kyle Fuller aba717b642 Add rx_title to UIViewController 2016-05-30 09:19:26 -07:00
Ilya Laryionau c6ae73f9ce extend CompositeDisposable with variadic init 2016-05-29 18:47:00 +03:00
Krunoslav Zaher bb4052fb1b Remove `hasObservers` from `SubjectType`. 2016-05-28 15:23:22 +02:00
Krunoslav Zaher bdb09885c2 Merge branch 'develop2' of git://github.com/pRizz/RxSwift into pRizz-develop2 2016-05-28 14:52:31 +02:00
Jesse Farless 75d1983afc Add RxTabBarDelegateProxy and UITabBar+Rx with delegate methods 2016-05-28 14:27:19 +02:00
Ben Shewmake db62a3cf3f Added changed '.subscribe' to '.subscribeNext' to alleviate error output in debug console. 2016-05-27 17:57:09 -06:00
Krunoslav Zaher d2eec7c478 Merge branch 'AndrewSB-feature/uialert-action' into develop 2016-05-27 23:27:19 +02:00
Krunoslav Zaher a5f1d1eef7 Merge branch 'feature/uialert-action' of git://github.com/AndrewSB/RxSwift into AndrewSB-feature/uialert-action 2016-05-27 23:24:50 +02:00
Krunoslav Zaher 6b038ad039 Merge pull request #701 from TheArtOfEngineering/swift-3.0
Add Swift 3 swift-DEVELOPMENT-SNAPSHOT-2016-05-09 compatibility.
2016-05-27 22:48:26 +02:00
Krunoslav Zaher 0e75ad3cf0 Improves CI by killing iOS simulator before each batch of tests to prevent deadlocks caused in Apple code. 2016-05-27 22:36:55 +02:00
Krunoslav Zaher e902c8b7f6 Merge remote-tracking branch 'origin/develop' into develop 2016-05-27 22:34:36 +02:00
Krunoslav Zaher c742831992 Merge branch 'punty-uipagecontrol-add-rx' into develop 2016-05-27 22:34:12 +02:00
Krunoslav Zaher 38f5eb210f Merge branch 'uipagecontrol-add-rx' of git://github.com/punty/RxSwift into punty-uipagecontrol-add-rx 2016-05-27 22:34:01 +02:00
Krunoslav Zaher eeabccf348 Merge pull request #711 from devxoul/fix-typo-docs-units
Fix typo in Documentation/Units.md
2016-05-26 14:10:50 +02:00
Jeon Suyeol d1713a8ac5 Fix typo in Documentation/Units.md 2016-05-26 04:17:52 +09:00
Krunoslav Zaher 31ebe46a16 Merge pull request #710 from larryonoff/bugfix/fix-typo
fix typo
2016-05-25 14:17:07 +02:00
Krunoslav Zaher d1393da8eb Merge pull request #703 from wddwycc/patch-2
Fix Blurred demonstration of 'concat demo'.
2016-05-24 11:42:17 +02:00
Tyler Cloutier 94833e438d Add Swift 3 swift-DEVELOPMENT-SNAPSHOT-2016-05-09 compatibility. 2016-05-22 14:43:47 -07:00
Ilya Laryionau 3693809b34 fix typo 2016-05-22 22:58:49 +02:00
Krunoslav Zaher e1bfa8c7ea Merge pull request #700 from carlosypunto/FixSpellingInGeolocationService
Fix spelling and reactivate access to preferences panel
2016-05-21 21:25:26 +02:00
Carlos García 5269932678 Fix spelling and reactivate access to preferences panel
Related to Pull Request:
https://github.com/ReactiveX/RxSwift/pull/623/files
2016-05-21 17:05:14 +02:00
Krunoslav Zaher cf2433e665 Fixes contact info. 2016-05-21 16:17:17 +02:00
Krunoslav Zaher a2b00547b8 Merge pull request #699 from solidcell/code-of-conduct
Add a code of conduct markdown
2016-05-21 16:09:34 +02:00
Jesse Farless 45133039c3 Add a code of conduct markdown
It still requires the email address to be updated
to whomever should be the point of contact
2016-05-21 12:20:53 +02:00
Krunoslav Zaher eda25e28ff Simplifies sectioned view extensions. 2016-05-20 22:34:13 +02:00
闻端Carl 607ebfbf3d Fix Demo
The output is of "concat example" is :  

Next(🍎)
Next(🍐)
Next(🍊)
Next(🐱)
Next(🐭)

If people do not use 'concat()', the result is the same, the demo cannot show the effect of 'concat()', which is "waiting for each sequence to terminate successfully before emitting elements from the next sequence"

so I add one line code for better demonstration.
2016-05-19 23:24:35 +08:00
Krunoslav Zaher 4b3056b81f Improves unit tests. 2016-05-19 12:25:57 +02:00
Peter Ryszkiewicz 185f66af90 Merge branch 'develop' into develop2
# Conflicts:
#	Rx.xcodeproj/project.pbxproj
2016-05-18 20:48:58 -05:00
Peter Ryszkiewicz 45042307ac Added unit tests for the hasObservers var. 2016-05-18 19:47:01 -05:00
Peter Ryszkiewicz 66230b7afe Fixed compilation of unit tests 2016-05-18 16:56:24 -05:00
Krunoslav Zaher e61b62d64f Merge branch 'sergdort-UIPickerView+Rx' into develop 2016-05-18 22:14:59 +02:00
Krunoslav Zaher b1dd82e831 Merge branch 'UIPickerView+Rx' of git://github.com/sergdort/RxSwift into sergdort-UIPickerView+Rx 2016-05-18 22:14:45 +02:00
Krunoslav Zaher 49b1481dff Updates RxDataSources. 2016-05-15 20:44:41 +02:00
Krunoslav Zaher 8a3b47953d Changes 2.5 to 2.5.0. 2016-05-15 18:28:31 +02:00
Krunoslav Zaher 33f2487a41 Adds 2.5.0 changes to CHANGELOG. 2016-05-15 18:28:31 +02:00
Krunoslav Zaher 3aa3850a74 Makes `NSTextField` implement `RxTextInput`. 2016-05-15 18:28:31 +02:00
Krunoslav Zaher 69b45ed364 Fixes Wikipedia automation tests. 2016-05-15 18:28:31 +02:00
Krunoslav Zaher aed5ac864a Improves delegate proxy messaging. #675 2016-05-15 18:28:31 +02:00
Krunoslav Zaher 0c34e28d38 Turns off bitcode for RxTests. #584 2016-05-15 18:28:31 +02:00
Krunoslav Zaher 761e9fea8b Release 2.5 2016-05-15 18:28:31 +02:00
Krunoslav Zaher 6b8738752f Merge pull request #685 from carlosypunto/moreComprensibleActivityIndicator
More comprensible `ActivityIndicator`
2016-05-15 16:34:27 +02:00
Carlos García f44393c1d8 More comprensible `ActivityIndicator` 2016-05-15 15:23:08 +02:00
Krunoslav Zaher fcbdc00f24 Merge branch 'feature/update-playground' into develop 2016-05-15 13:23:24 +02:00
Jesse Farless 4de6a0b621 Improve language in comment 2016-05-15 13:21:44 +02:00
Jesse Farless 7e64194403 Use new Swift selector syntax in comment 2016-05-15 13:21:44 +02:00
Jesse Farless 3194efced8 Update comment to use new non-deprecated method 2016-05-15 13:21:44 +02:00
Jesse Farless fb97732d85 Fix argument key in comment 2016-05-15 13:21:44 +02:00
Jesse Farless b4ce5629cc Typo in comment 'extensions' with an 's' 2016-05-15 13:21:44 +02:00
Krunoslav Zaher a9135f1169 Improves documentation for `DelegateProxy.observe`. #654 2016-05-15 13:21:44 +02:00
Krunoslav Zaher 02413a176e Adds unit test for only setting different text values. 2016-05-15 13:21:44 +02:00
Krunoslav Zaher 993cc1af76 Provides explanations for check. 2016-05-15 13:21:44 +02:00
Krunoslav Zaher 21904f14c9 Fixes problems with two way binding that was caused by `rx_text` and always setting the text value even when the value was equal, and thus clearing the marked text state. #649 2016-05-15 13:21:44 +02:00
Scott Gardner aca9950fdc Add missing Next link 2016-05-14 16:54:54 -05:00
Scott Gardner 84c42e6dd6 Split Error Handling and Debugging Operators into separate pages 2016-05-14 16:50:47 -05:00
Krunoslav Zaher 1c03845341 Merge pull request #683 from solidcell/delegate-proxy-typos
DelegateProxyType comment updates
2016-05-14 21:23:24 +02:00
Scott Gardner 990c967052 Add missing dividers between examples 2016-05-14 13:23:57 -05:00
Scott Gardner 52005f4096 Disable RxSwift.resourceCount example outside of playground 2016-05-14 12:34:18 -05:00
Scott Gardner 3efaeac3ad Rename Debugging_and_Error_Handling_Operators to Error_Handling_and_Debugging_Operators and update 2016-05-14 06:56:55 -05:00
Scott Gardner bc81ce4252 Update Rx.swift 2016-05-14 06:56:12 -05:00
Jesse Farless 8a5e303af9 Improve language in comment 2016-05-14 10:47:04 +02:00
Jesse Farless f4ddfbda39 Use new Swift selector syntax in comment 2016-05-14 10:46:38 +02:00
Jesse Farless 5a26b2bc74 Update comment to use new non-deprecated method 2016-05-14 10:45:24 +02:00
Jesse Farless 665d9c7fbc Fix argument key in comment 2016-05-14 10:44:39 +02:00
Jesse Farless e6090fff58 Typo in comment 'extensions' with an 's' 2016-05-14 10:43:11 +02:00
Scott Gardner e0923c9f0c Move Test Error to SupportCode 2016-05-13 19:03:18 -05:00
Krunoslav Zaher 4c23f61b81 Improves documentation for `DelegateProxy.observe`. #654 2016-05-14 02:02:25 +02:00
Krunoslav Zaher cd247fe639 Merge pull request #677 from ReactiveX/feature/IME_input
Fixes problems with two way binding that was caused by `rx_text` and …
2016-05-14 01:29:43 +02:00
Krunoslav Zaher 3fa44935a1 Adds unit test for only setting different text values. 2016-05-14 01:20:54 +02:00
Scott Gardner 964f5be0d6 Update Connectable Operators 2016-05-13 17:39:51 -05:00
Scott Gardner 632e8ce154 Update Connectable Operators 2016-05-13 17:25:03 -05:00
Scott Gardner 6a1346c5c7 Update SupportCode 2016-05-13 17:24:51 -05:00
Scott Gardner 8b63f25fe1 Update Mathematical and Aggregate Operators 2016-05-13 15:46:04 -05:00
Scott Gardner 4046c1163c Update skipUntil example 2016-05-13 14:49:00 -05:00
Scott Gardner 4b03165635 Combine Filtering and Conditional Operators pages 2016-05-13 14:47:19 -05:00
Scott Gardner 38dec119e9 Update Combining Operators and move before Transforming Operators 2016-05-13 14:01:43 -05:00
Scott Gardner a68c07beb5 Update Filtering Operators 2016-05-13 11:28:07 -05:00
Scott Gardner c0bebbb795 Update Transforming Operators 2016-05-13 11:27:45 -05:00
sergdort 43269fa279 Added `rx_itemSelected` for UIPickerView 2016-05-13 10:55:21 +03:00
Krunoslav Zaher bee2ce5e4b Provides explanations for check. 2016-05-13 00:47:44 +02:00
Krunoslav Zaher 1aa1b570b0 Fixes problems with two way binding that was caused by `rx_text` and always setting the text value even when the value was equal, and thus clearing the marked text state. #649 2016-05-13 00:38:26 +02:00
Scott Gardner 3771e63a4c Minor update to Rx.playground based on feedback from kzaher 2016-05-12 16:04:32 -05:00
Scott Gardner ef62979f62 Change flatMapLatest example in Rx.playground to initially use flatMap 2016-05-12 15:34:10 -05:00
Scott Gardner 070139a4c4 Update playground...
Table of Contents
Introduction
Creating and Subscribing to Observables
Working with Subjects
Transforming Operators
2016-05-12 15:30:38 -05:00
Krunoslav Zaher 26dad8095f Merge pull request #676 from solidcell/language-tweaks
Fix typos and tweak language in docs
2016-05-12 22:27:49 +02:00
Jesse Farless 64e40ef604 Fix typos and tweak language in docs 2016-05-12 13:42:29 +02:00
Krunoslav Zaher fc519c3bb2 Merge pull request #674 from kumapo/add-rx-title-to-navigation-item
Add rx_title property to UINavigationItem
2016-05-11 21:30:03 +02:00
kumapo 1252338905 Add documentation for UINavigationItem+Rx 2016-05-12 01:28:12 +09:00
kumapo 02d30f846c Add unit tests for UINavigationItem+Rx 2016-05-12 00:24:06 +09:00
kumapo e1a6847fbf Fix pre-release-tests error 2016-05-09 20:47:54 +09:00
kumapo cbe17b7c1c Add rx_title property to UINavigationItem 2016-05-09 18:20:53 +09:00
Andrew Breckenridge af7c011a53 add forgotten parentheses to test function declarations 2016-05-08 15:08:43 -07:00
Krunoslav Zaher 92b8a51891 Orta's improvements. 2016-05-09 00:05:04 +02:00
Krunoslav Zaher ce5fcd1f4f Improves documentation. 2016-05-08 23:52:26 +02:00
Carlos García a2306bdf90 adds a little note about subscrition 2016-05-08 23:52:26 +02:00
Carlos García 207761c2a7 improve playgrouds
Thanks @finneycanhelp for help me to improve my English writing
2016-05-08 23:52:26 +02:00
Krunoslav Zaher cf0ef0b941 Merge pull request #673 from acecilia/develop
Fix to support iOS 7
2016-05-08 22:57:06 +02:00
Andrés Cecilia 881909a687 Fix to support iOS 7 2016-05-08 22:42:53 +02:00
Krunoslav Zaher b202c91991 Fixes unit tests for `installForwardDelegate`. 2016-05-08 22:10:34 +02:00
Krunoslav Zaher d197ce0fbb Exposes `installForwardDelegate` and transforms `proxyForObject` into protocol extension. 2016-05-08 21:32:02 +02:00
Andrew Breckenridge c4e83f3f34 add UIAlertAction tests to Control+RxTests+UIKit 2016-05-07 12:31:31 -07:00
Andrew Breckenridge 0188dccd4f create UIAlertAction+Rx.swift 2016-05-07 12:23:50 -07:00
Krunoslav Zaher 9b6f069f81 Merge pull request #669 from vburojevic/develop
Unwrap optional forwardToDelegate in assert message
2016-05-07 00:00:14 +02:00
Vedran Burojevic 139559f410 Unwrap optional forwardToDelegate in assert message 2016-05-06 20:52:08 +02:00
Krunoslav Zaher bb1b653ee0 Merge pull request #668 from rad182/develop
fixed typos
2016-05-06 15:30:12 +02:00
Royce Dy 0dec95efcb fixed typos 2016-05-06 10:49:51 +08:00
Krunoslav Zaher 81b9ff7322 Merge pull request #660 from ReactiveX/typed-gesture-recognizer-extension
Typed gesture recognizer extension
2016-05-03 23:24:18 +02:00
Scott Gardner caf4c497a6 Update Event...
Revise documentation
Follow convention to adopt and conform to a protocol in the extension
2016-05-03 09:33:26 -05:00
Yury Korolev 5fff8d2b7f Better code formatting 2016-05-03 12:05:21 +03:00
Yury Korolev 2e6cfdc15c Docs for Reactive protocol 2016-05-03 12:01:23 +03:00
Roy Li b8ecb446d8 Added lock when accessing _observers.count to ensure thread safety
I also moved _lock from ReplayBufferBase to ReplaySubject to enable
hasObservers property in ReplaySubject.
2016-05-02 20:20:36 -05:00
Roy Li 490118fdad Added comments for hasObservers
As requested, I added comments for the property hasObservers
2016-05-02 20:14:58 -05:00
Krunoslav Zaher a4ae75d03f Merge pull request #657 from thanegill/uilabel-rx_text
UILabel rx_text as `String?`
2016-05-02 21:29:46 +02:00
Yury Korolev c5a21681a8 Rename Rx to Reactive protocol 2016-05-02 20:05:38 +03:00
Yury Korolev 3e1b2d0789 Typed rx_event for UIGestureRecognizer 2016-05-02 13:36:09 +03:00
Thane Gill 37d685690c UILabel rx_text as `String?` 2016-04-30 11:13:38 -07:00
Krunoslav Zaher 779eb92d9e Fixes copyright in header. 2016-04-30 12:06:00 +02:00
Roy Li 3a57927a92 Added hasObservers on each of the Subject classes
Added var hasObservers: Bool { get } to the SubjectType protocol.

Then made all the Subject classes conform to the protocol by providing
hasObservers as a computed property.
2016-04-29 23:15:02 -05:00
Krunoslav Zaher 7687ad4c68 Updates RxDataSources. 2016-04-29 20:52:00 +02:00
Krunoslav Zaher 0288ba78d5 Merge pull request #643 from Nirma/develop
Dry up lock / unlock logic in Lock.swift
2016-04-29 20:34:51 +02:00
Krunoslav Zaher b3036c037b Merge pull request #647 from Nirma/grammar_fix
Grammar fixes and minor clarifications in Intro playground text.
2016-04-28 23:04:05 +02:00
Krunoslav Zaher 27d722e52d Merge pull request #648 from Nirma/subject_clarification
Add Clarification to BehaviorSubject and grammar fixes
2016-04-28 23:02:44 +02:00
Nicholas Maccharoli 8bbc952c6f Add Clarification to BehaviorSubject and grammar fixes 2016-04-26 15:08:56 +09:00
Nicholas Maccharoli 3363432c66 Grammar fix in Intro playground 2016-04-26 14:22:18 +09:00
Krunoslav Zaher c2ad533b1d Merge pull request #646 from Nirma/logic_fix
Shorten logic of VirtualTimeConverterType's computed properties
2016-04-25 09:39:55 +02:00
Nicholas Maccharoli ee20ea8c82 Shorten logic of VirtualTimeConverterType's computed properties 2016-04-25 16:25:01 +09:00
Francesco Puntillo b384c3e982 Adding Unit testing for UIPageControl+Rx 2016-04-25 10:50:34 +08:00
Nicholas Maccharoli 9e345e3645 Dry up lock / unlock logic in Lock.swift 2016-04-25 03:10:06 +09:00
Krunoslav Zaher 7133d6a6e5 Merge pull request #638 from Nirma/lastindex_improvement
Make lastIndexOf search from end of string to start
2016-04-24 15:43:39 +02:00
Krunoslav Zaher a96321638a Merge pull request #641 from ReactiveX/partial-application
Use partial application with AnonymousDisposable if possible
2016-04-24 15:42:17 +02:00
Yury Korolev 353b0b55c3 Use partial application with AnonymousDisposable if possible 2016-04-23 21:22:10 +03:00
Krunoslav Zaher 347e81244c Merge pull request #640 from garnett/delete-empty-file
Delete empty extension
2016-04-22 23:49:58 +02:00
Denis Lebedev ca070e6a36 Delete empty extension 2016-04-22 22:44:04 +01:00
Krunoslav Zaher 7622d9c5b7 Fixes for Linux. 2016-04-22 21:07:20 +02:00
Krunoslav Zaher c11c7a8f97 Unifies atomics on Linux. 2016-04-22 21:01:45 +02:00
Krunoslav Zaher 4e6880d218 Fixes for RxSwift and Swift 3.0. 2016-04-22 20:49:18 +02:00
Krunoslav Zaher 1b5cd9ecb5 Fixing swift 3.0 warnings. 2016-04-22 13:14:41 +02:00
Krunoslav Zaher c4ca775bdc Changes for Swift 3.0. 2016-04-22 13:14:41 +02:00
Krunoslav Zaher 6b259b6618 Fixes warnings. 2016-04-22 13:03:16 +02:00
Krunoslav Zaher 58c8e0e802 Merge branch 'Calvin-Huang-resolve_ios_example_warning' into develop 2016-04-22 12:26:59 +02:00
Krunoslav Zaher b2cf5ce567 Fixes problems with WikipediaImageSearch. 2016-04-22 12:26:14 +02:00
Krunoslav Zaher 6125245a73 Merge branch 'resolve_ios_example_warning' of git://github.com/Calvin-Huang/RxSwift into Calvin-Huang-resolve_ios_example_warning 2016-04-22 11:51:17 +02:00
Nicholas Maccharoli 5b35246953 Make lastIndexOf search from end of string to start 2016-04-22 14:34:31 +09:00
Calvin 68bf69e086 UISearchController's default animation will shift searchBar to the top.
This will trigger rx_contentOffset then close keyboard will makes users confused.
Filter situation that searchController is being present.
2016-04-22 12:30:28 +09:00
Calvin 66abcd07dc - Delete UISearchDisplayController, use UISearchController instead.
- Add IBOutlet searchBarContainer to setup searchBar.
2016-04-22 11:52:43 +09:00
Krunoslav Zaher b5491dd404 Merge pull request #632 from Nirma/simplify_queue
Simplify Queue.swift's init logic
2016-04-21 22:53:40 +02:00
Krunoslav Zaher 0c53b24b18 Fixes unit tests. 2016-04-21 22:52:18 +02:00
Nicholas Maccharoli 4d18ec0558 Simplify Queue.swift's init logic 2016-04-21 22:51:55 +02:00
Krunoslav Zaher 5283328321 Merge pull request #635 from Nirma/queue_defer
Leverage defer to make Queue's code more concise
2016-04-21 22:20:54 +02:00
Krunoslav Zaher 4e78d66857 Merge remote-tracking branch 'origin/develop' into develop 2016-04-21 22:10:29 +02:00
Krunoslav Zaher 0536a8868f Updates CocoaPods integration documentation. 2016-04-21 21:31:05 +02:00
Krunoslav Zaher bad39e0628 Merge pull request #633 from 53ningen/queue
make _initialCapacity property of Queue immutable
2016-04-21 11:42:35 +02:00
Nicholas Maccharoli 13ec2c0fea Leverage defer to make Queue's code more concise 2016-04-21 18:40:34 +09:00
gomi_ningen 439b70d258 make _initialCapacity property of Queue immutable 2016-04-21 18:04:31 +09:00
Nicholas Maccharoli 0c82695990 Simplify Queue.swift's init logic 2016-04-21 16:18:03 +09:00
Calvin 656669699a - Resolve storyboard warning.
- Remove wikipedia scene's search display controller and search bar, add search bar container.
2016-04-21 15:29:23 +09:00
Krunoslav Zaher 6dd6c9b211 Merge branch 'develop' 2016-04-20 13:55:17 +02:00
Krunoslav Zaher 48b782d761 Removes book on left side of README.md 2016-04-20 13:54:59 +02:00
Orta 78220fd37b Update README.md 2016-04-20 13:54:59 +02:00
Orta 91dc31b9ed Use a fancy table in the README 2016-04-20 13:54:59 +02:00
Krunoslav Zaher 0c7ca38cd7 Great readme commit. 2016-04-20 13:54:59 +02:00
Krunoslav Zaher 6455a64acf Removes book on left side of README.md 2016-04-20 13:54:09 +02:00
Orta 2eb01273b8 Update README.md 2016-04-20 12:39:16 +01:00
Orta 91e7a3dead Use a fancy table in the README 2016-04-20 11:48:31 +01:00
Krunoslav Zaher 411c4c284c Great readme commit. 2016-04-20 12:08:42 +02:00
Krunoslav Zaher c7fc68bfc1 Merge pull request #628 from garnett/patch-1
Rename outdated class name
2016-04-19 10:04:59 +02:00
Denis Lebedev 96de182dd3 Rename outdated class name 2016-04-18 22:45:21 +01:00
Krunoslav Zaher 3294458b87 Adds `rx_willDisplayCell` and `rx_didEndDisplayingCell` to `UITableView`. 2016-04-18 23:11:18 +02:00
Krunoslav Zaher 3668f360d7 Merge pull request #617 from ReactiveX/less-count-and-last
Use guard ... _generators.last instead of count check and last!
2016-04-17 18:23:10 +02:00
Krunoslav Zaher 72edf869a0 Removes `distinctUntilChanged` because is was creating a hidden state that can cause issues in some situations. 2016-04-17 17:14:55 +02:00
Francesco Puntillo 56119d3e91 Merge branch 'uipagecontrol-add-rx_master' into uipagecontrol-add-rx 2016-04-15 18:07:11 +08:00
Krunoslav Zaher 756f17c848 Merge pull request #616 from catalandres/patch-1
Update Contents.swift
2016-04-14 14:19:14 +02:00
Francesco Puntillo 2c7a403dae adjust formatting for UIPageControl+RX 2016-04-14 17:14:20 +08:00
Francesco Puntillo 8b4642a1c0 add UIPageControl to RxCocoa 2016-04-14 15:45:35 +08:00
Yury Korolev 15b6bfc7dd Do not change return logic 2016-04-13 11:39:19 +03:00
Yury Korolev aa41626c39 Use guard ... _generators.last instead of count check and last! 2016-04-13 11:23:11 +03:00
Krunoslav Zaher ceee55e6d9 Removes is on WiFi check from main queue. 2016-04-12 12:17:10 +02:00
Krunoslav Zaher c193b5db52 Improves reachability service. 2016-04-12 12:06:07 +02:00
Krunoslav Zaher 7b6a6b5f27 Enables Bitcode for tvOS. 2016-04-11 09:51:06 +02:00
Krunoslav Zaher d8228eeea7 Adds 2.4 to `CHANGELOG.md`. 2016-04-11 00:31:56 +02:00
Krunoslav Zaher e16ce89f3f Documents parts of `RxCocoa`. 2016-04-11 00:31:26 +02:00
Krunoslav Zaher 12467ebc32 Release 2.4 2016-04-11 00:17:12 +02:00
Krunoslav Zaher 681bbf8c00 Updates Linux tests. 2016-04-11 00:16:11 +02:00
Krunoslav Zaher 39a87bfcfd Fixes anomaly with `multicast` subscription disposal. 2016-04-11 00:07:54 +02:00
Krunoslav Zaher 18cf20820f Merge pull request #550 from stack/uisearchbar-cancel
UISearchBar Cancel Event
2016-04-10 12:57:13 +02:00
Stephen H. Gerstacker d6731613d9 Switched to ButtonClicked over Tap for UISearchBar delegate methods 2016-04-09 18:22:29 -04:00
Krunoslav Zaher 45540eb574 Improves UITableView and UICollectionView tests. 2016-04-10 00:06:28 +02:00
Krunoslav Zaher f40826c148 Merge pull request #608 from 53ningen/feature/break
removed unnecessary `break`
2016-04-08 22:30:45 +02:00
gomi_ningen 1ce3622c10 removed unnecessary `break` 2016-04-08 13:44:59 +09:00
Krunoslav Zaher f50a33c1e2 Fixes warnings with deprecated selector specifications. 2016-04-08 00:08:03 +02:00
Krunoslav Zaher 43b0c306d8 Updates comments. 2016-04-07 23:25:25 +02:00
Krunoslav Zaher 77d72dcaee Updates comments. 2016-04-07 23:22:37 +02:00
Krunoslav Zaher 0b90d9d053 Merge pull request #604 from 53ningen/feature/typo
fixed typo
2016-04-07 12:39:56 +02:00
Krunoslav Zaher 26032f7ce1 Merge pull request #607 from shingt/replace-remaining-failWith
Replace failWith with error in examples
2016-04-07 12:39:35 +02:00
Krunoslav Zaher 8bf939d17d Merge pull request #601 from monotonique/fix_link
Fixed Link to Dicision Tree
2016-04-07 12:39:05 +02:00
Krunoslav Zaher 837e9e7a69 Merge pull request #602 from 53ningen/feature/comment
fixed a comment
2016-04-07 12:34:48 +02:00
gomi_ningen b4a5d05c09 fixed typo 2016-04-07 03:56:08 +09:00
gomi_ningen f72c4d604f fixed a comment 2016-04-06 14:21:07 +09:00
shingt 5b7dff230f Replace failWith with error in examples 2016-04-06 09:48:30 +09:00
Andrés Catalán 80aaef06c2 Update Contents.swift
The comment to `toObservable` referred to another function.
2016-04-05 18:54:10 -04:00
Krunoslav Zaher 5c1adf29df Small fix for Tips.md 2016-04-05 21:53:11 +02:00
Krunoslav Zaher 7773d2828e Merge pull request #593 from kkdevenda/develop
Removed ambiguity in the documentation of 'value' property
2016-04-02 17:43:55 +02:00
krishna a2edb47807 Removed ambiguity in the documentation of 'value' property 2016-04-02 19:46:13 +05:30
Krunoslav Zaher 890fc04106 Merge pull request #587 from chanelten/remove_compiler_warnings
Remove compiler warnings
2016-03-31 00:01:54 +02:00
Krunoslav Zaher 7ad3365296 Merge pull request #585 from pixyzehn/feature/fix-getting-started-text
Use 'Completed' instead of 'Complete'
2016-03-30 23:13:08 +02:00
Alexander I. Kovács a30288e5f9 Disable bitcode for test targets
Setting ENABLE_BITCODE to NO for test targets removes the following compiler warnings when building the project via Carthage and Xcode 7.3:

ld: warning: Auto-Linking supplied '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework/XCTest', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework/XCTest' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target.
2016-03-30 18:07:55 +09:00
Alexander I. Kovács a5c9e6ad65 Do not require application extension API only for test targets
Setting APPLICATION_EXTENSION_API_ONLY to NO for test targets removes the following compiler warnings when building the project via Carthage and Xcode 7.3:

ld: warning: linking against a dylib which is not safe for use in application extensions: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Frameworks/XCTest.framework/XCTest
2016-03-30 18:07:38 +09:00
Nagasawa Hiroki 8a1e87e6b8 Use 'Completed' instead of 'Complete' 2016-03-29 18:56:11 +09:00
Krunoslav Zaher 7dffae6dc8 Merge pull request #578 from tarunon/feature/drive_to_variable
Adding drive to Variable operator to Driver
2016-03-28 22:11:50 +02:00
Krunoslav Zaher dc4857252b Merge pull request #581 from bricklife/rendering-playgrounds
Turns on 'Render Documentation' for playgrounds again
2016-03-28 19:54:01 +02:00
Krunoslav Zaher 1615ab88f3 Merge pull request #582 from kkdevenda/master
Documentation for skipUntil corrected
2016-03-28 19:53:40 +02:00
Krishna 5a112ed064 Documentation for skipUntil corrected
It seems a copy paste error as documentation for both `skipUntil` and `takeUntil` was same.
I have corrected the documentation for `skipUntil` keeping `takeUntil` intact.
2016-03-28 16:49:07 +05:30
Shinichiro Oba c2ab272cc7 Turns on 'Render Documentation' for playgrounds. 2016-03-28 11:46:43 +09:00
Stephen H. Gerstacker f58d032d34 tvOS Fixes for UISearchBar
- `searchBarCancelButtonClicked:` is only available on iOS.
- UISearchBar instantiation is not supported on tvOS, so all subclass
  delegate methods and tests are skipped.
2016-03-27 21:31:53 -04:00
Krunoslav Zaher 6292a3303a Merge pull request #556 from sergdort/rx_search_controller_delegate_proxy
Added reactive extensions for UISearchController
2016-03-27 20:23:57 +02:00
Stephen H. Gerstacker 2db92e9727 Upgraded UISearchBar selectors to Swift 2.2 selectors 2016-03-26 21:02:09 -04:00
Stephen H. Gerstacker dd37af0069 Additional UISearchBar Methods
- Added the searchTap for the "searchBarSearchButtonClicked:" delegate
  method.

- Added the "rx_createDelegateProxy" method to UISearchBar.
2016-03-26 20:57:23 -04:00
Krunoslav Zaher 157d7f1328 Merge pull request #577 from fantattitude/patch-2
Markdown typo on Why.md
2016-03-26 11:32:24 +01:00
tarunon 1570dc70c5 adding drive to variable operator to Driver 2016-03-26 00:26:24 +09:00
Vivien Leroy e0e113f969 Markdown typo on Why.md
Sentence was not bold because of space after the two stars
2016-03-25 15:24:42 +01:00
Krunoslav Zaher 1ed2daed68 Merge pull request #569 from ejensen/typos
Typo fixes
2016-03-23 23:07:50 +01:00
Krunoslav Zaher 4568ac6592 Merge pull request #570 from ejensen/mixed-tabs
Correct mixed indentation
2016-03-23 22:55:30 +01:00
Eric Jensen 9899bd7d39 Use modern dictionary syntax 2016-03-22 20:12:06 -07:00
Eric Jensen ddf9cdd33f Correct typos 2016-03-22 20:10:44 -07:00
Eric Jensen 2b0dd31a9f Correct mixed indentation by replacing tabs with spaces 2016-03-22 20:04:39 -07:00
George Lin 4a37077db1 Fixed Link to Dicision Tree
- removed a redundant parenthesis
2016-03-23 10:48:12 +08:00
Stephen H. Gerstacker e1ea14819c Merge branch 'develop' into uisearchbar-cancel 2016-03-22 20:41:09 -04:00
sergdort 2f16a4faa7 Adds reactive extensions for UISearchController and tests to cover them 2016-03-22 16:50:07 +02:00
Stephen H. Gerstacker f91b86b8d2 Merge branch 'develop' into uisearchbar-cancel 2016-03-22 06:57:56 -04:00
Stephen H. Gerstacker 6b8fe1eabe Merge branch 'uisearchbar-cancel' of https://github.com/stack/RxSwift into uisearchbar-cancel 2016-03-13 21:05:25 -04:00
Stephen H. Gerstacker 92911a6876 Added rx_cancelTap for the searchBarCancelButtonClicked: delegate method 2016-03-13 21:04:31 -04:00
Stephen H. Gerstacker 3f6bcf356e Added for the delegate method 2016-03-13 21:02:32 -04:00
521 changed files with 15845 additions and 12262 deletions

278
.jazzy.yml Normal file
View File

@ -0,0 +1,278 @@
---
custom_categories:
- name: RxSwift
children:
- AnyObserver
- Cancelable
- ConnectableObservableType
- Disposable
- Errors
- Event
- ImmediateSchedulerType
- Observable+Extensions
- Observable
- ObservableConvertibleType
- ObservableType
- ObserverType
- Rx
- RxMutableBox
- SchedulerType
- name: RxSwift/Concurrency
children:
- AsyncLock
- Lock
- LockOwnerType
- SynchronizedDisposeType
- SynchronizedOnType
- SynchronizedSubscribeType
- SynchronizedUnsubscribeType
- name: RxSwift/DataStructures
children:
- Bag
- InfiniteSequence
- PriorityQueue
- Queue
- name: RxSwift/Disposables
children:
- AnonymousDisposable
- BinaryDisposable
- BooleanDisposable
- CompositeDisposable
- DisposeBag
- DisposeBase
- NAryDisposable
- NopDisposable
- RefCountDisposable
- ScheduledDisposable
- SerialDisposable
- SingleAssignmentDisposable
- StableCompositeDisposable
- SubscriptionDisposable
- name: RxSwift/Extensions
children:
- String+Rx
- name: RxSwift/Observables/Implementations
children:
- AddRef
- Amb
- AnonymousObservable
- Buffer
- Catch
- CombineLatest+arity
- CombineLatest+CollectionType
- CombineLatest
- Concat
- ConnectableObservable
- Debug
- Deferred
- DelaySubscription
- DistinctUntilChanged
- Do
- ElementAt
- Empty
- Error
- Filter
- Generate
- Just
- Map
- Merge
- Multicast
- Never
- ObserveOn
- ObserveOnSerialDispatchQueue
- Producer
- Range
- Reduce
- RefCount
- Repeat
- RetryWhen
- Sample
- Scan
- Sequence
- ShareReplay1
- ShareReplay1WhileConnected
- SingleAsync
- Sink
- Skip
- SkipUntil
- SkipWhile
- StartWith
- SubscribeOn
- Switch
- Take
- TakeLast
- TakeUntil
- TakeWhile
- Throttle
- Timeout
- Timer
- ToArray
- Using
- Window
- WithLatestFrom
- Zip+arity
- Zip+CollectionType
- Zip
- name: RxSwift/Observables
children:
- Observable+Aggregate
- Observable+Binding
- Observable+Concurrency
- Observable+Creation
- Observable+Debug
- Observable+Multiple
- Observable+Single
- Observable+StandardSequenceOperators
- Observable+Time
- name: RxSwift/Observers
children:
- AnonymousObserver
- ObserverBase
- TailRecursiveSink
- name: RxSwift/Platform
children:
- Platform.Darwin
- Platform.Linux
- name: RxSwift/Schedulers
children:
- ConcurrentDispatchQueueScheduler
- ConcurrentMainScheduler
- CurrentThreadScheduler
- DispatchQueueSchedulerQOS
- HistoricalScheduler
- HistoricalSchedulerTimeConverter
- ImmediateScheduler
- MainScheduler
- OperationQueueScheduler
- RecursiveScheduler
- SchedulerServices+Emulation
- SerialDispatchQueueScheduler
- VirtualTimeConverterType
- VirtualTimeScheduler
- name: RxSwift/Schedulers/Internal
children:
- AnonymousInvocable
- InvocableScheduledItem
- InvocableType
- ScheduledItem
- ScheduledItemType
- name: RxSwift/Subjects
children:
- BehaviorSubject
- PublishSubject
- ReplaySubject
- SubjectType
- Variable
- name: RxCocoa/Common
children:
- CLLocationManager+Rx
- DelegateProxy
- DelegateProxyType
- KVORepresentable+CoreGraphics
- KVORepresentable+Swift
- KVORepresentable
- Logging
- NSLayoutConstraint+Rx
- Observable+Bind
- Reactive
- RxCocoa
- RxTarget
- RxTextInput
- SectionedViewDataSourceType
- name: RxCocoa/Common/CocoaUnits
children:
- ControlEvent
- ControlProperty
- UIBindingObserver
- name: RxCocoa/Common/CocoaUnits/Driver
children:
- ControlEvent+Driver
- ControlProperty+Driver
- Driver+Operators+arity
- Driver+Operators
- Driver+Subscription
- Driver
- ObservableConvertibleType+Driver
- Variable+Driver
- name: RxCocoa/Common/Observables/Implementations
children:
- ControlTarget
- DeallocObservable
- KVOObservable
- KVOObserver
- MessageSentObserver
- name: RxCocoa/Common/Observables
children:
- NSNotificationCenter+Rx
- NSObject+Rx+KVORepresentable
- NSObject+Rx+RawRepresentable
- NSObject+Rx
- NSURLSession+Rx
- name: RxCocoa/Common/Proxies
children:
- RxCLLocationManagerDelegateProxy
- name: RxCocoa/iOS/DataSources
children:
- RxCollectionViewReactiveArrayDataSource
- RxTableViewReactiveArrayDataSource
- name: RxCocoa/iOS/Events
children:
- ItemEvents
- name: RxCocoa/iOS
children:
- NSTextStorage+Rx
- UIActivityIndicatorView+Rx
- UIAlertAction+Rx
- UIApplication+Rx
- UIBarButtonItem+Rx
- UIButton+Rx
- UICollectionView+Rx
- UIControl+Rx
- UIDatePicker+Rx
- UIGestureRecognizer+Rx
- UIImagePickerController+Rx
- UIImageView+Rx
- UILabel+Rx
- UINavigationItem+Rx
- UIPageControl+Rx
- UIPickerView+Rx
- UIProgressView+Rx
- UIRefreshControl+Rx
- UIScrollView+Rx
- UISearchBar+Rx
- UISearchController+Rx
- UISegmentedControl+Rx
- UISlider+Rx
- UIStepper+Rx
- UISwitch+Rx
- UITabBarItem+Rx
- UITableView+Rx
- UITextField+Rx
- UITextView+Rx
- UIView+Rx
- UIViewController+Rx
- name: RxCocoa/iOS/Protocols
children:
- RxCollectionViewDataSourceType
- RxTableViewDataSourceType
- name: RxCocoa/iOS/Proxies
children:
- RxCollectionViewDataSourceProxy
- RxCollectionViewDelegateProxy
- RxImagePickerDelegateProxy
- RxPickerViewDelegateProxy
- RxScrollViewDelegateProxy
- RxSearchBarDelegateProxy
- RxSearchControllerDelegateProxy
- RxTableViewDataSourceProxy
- RxTableViewDelegateProxy
- RxTextStorageDelegateProxy
- RxTextViewDelegateProxy
- name: RxCocoa/OSX
children:
- NSButton+Rx
- NSControl+Rx
- NSImageView+Rx
- NSSlider+Rx
- NSTextField+Rx
- NSView+Rx

View File

@ -1,9 +1,13 @@
language: objective-c
osx_image: xcode7.3
osx_image: xcode8
notifications:
slack: rxswift:3ykt2Z61f8GkdvhCZTYPduOL
email: false
script: ./scripts/pre-release-tests.sh
script:
- "bundle exec danger --verbose"
- xcodebuild -version
- xcodebuild -showsdks
- ./scripts/all-tests.sh

View File

@ -3,6 +3,109 @@ All notable changes to this project will be documented in this file.
---
## Master
## [3.0.0.alpha.1](https://github.com/ReactiveX/RxSwift/releases/tag/3.0.0.alpha.1) (Xcode 8 beta 6 compatible 8S201h)
#### Features
* Modernizes API to be more consistent with Swift 3.0 API Design Guidelines
* Replaces `rx_*` prefix with `rx.*` extensions. (Inspired by `.lazy` collections API). We've tried annotate deprecated APIs with `@available(*, deprecated, renamed: "new method")` but trivial replacements aren't annotated.
* `rx_text` -> `rx.text`
* `rx_tap` -> `rx.tap`
* `rx_date` -> `rx.date`
* ...
* Deprecates `subscribeNext`, `subscribeError`, `subscribeCompleted` in favor of `subscribe(onNext:onError:onCompleted:onDisposed)` (The downsides of old extensions were inconsistencies with Swift API guidelines. They also weren't expressing that calling them actually performes additional subscriptions and thus potentially additional work beside just registering observers).
* Deprecates `doOnNext`, `doOnCompleted`, `doOnError` in favor of `do(onNext:onCompleted:onError:onSubscribe:onDisposed:)`
* Adds `onSubscribe` and `onDisposed` to `do` operator.
* Adds namespace for immutable disposables called `Disposables`
* Deprecates `AnonymousDisposable` in favor of `Disposables.create(with:)`
* Deprecates `NopDisposable` in favor of `Disposables.create()`
* Deprecates `BinaryDisposable` in favor of `Disposables.create(_:_:)`
* Deprecates `toObservable` in favor of `Observable.from()`.
* Replaces old javascript automation tests with Swift UI Tests.
* ...
#### Anomalies
* There is a problem using `UISwitch` extensions because it seems that a bug exists in UIKit that causes all `UISwitch` instances to leak. https://github.com/ReactiveX/RxSwift/issues/842
## [2.6.0](https://github.com/ReactiveX/RxSwift/releases/tag/2.6.0)
#### Features
* Adds Swift 2.3 compatibility.
* Adds `UIViewController.rx_title` extension.
* Adds `UIScrollView.rx_scrollEnabled` extension.
* Resolve static analysis issues relating to non-use of an assigned value, and potential null dereferences in RxCocoa's Objective-C classes.
* Changes `forwardDelegate` property type on `DelegateProxy` from `assign` to `weak`.
* Simplifies UITable/CollectionView data source generic parameters.
* Adds simple usage examples to UITable/CollectionView data source extensions.
* Documents UITable/CollectionView data source extensions memory management and adds unit tests to cover that documentation.
* Adds `.jazzy.yml`
* Adds `UITabBar` extensions and delegate proxy wrapper
* rx_didSelectItem
* rx_willBeginCustomizing
* rx_didBeginCustomizing
* rx_willEndCustomizing
* rx_didEndCustomizing
* Adds `UIPickerView` delegate proxy and extensions:
* rx_itemSelected
* Adds `UIAlertAction.rx_enabled` extension.
* Adds `UIButton.rx_title(controlState: UIControlState = .Normal)` extension.
* Adds `UIPageControl.rx_currentPage` extension.
* Adds `hasObservers` property to `*Subject`.
#### Anomalies
* Fixes problem with UITable/CollectionView releasing of data sources when result subscription disposable wasn't retained.
* Fixes all Xcode analyzer warnings
## [2.5.0](https://github.com/ReactiveX/RxSwift/releases/tag/2.5.0)
#### Features
* Exposes `installForwardDelegate`.
* Adds `proxyForObject` as protocol extension and deprecates global function version.
* Improves `installForwardDelegate` assert messaging.
* Improves gesture recognizer extensions to use typed gesture recognizers in `rx_event`.
* Adds `RxTextInput` protocol to enable creating reactive extensions for `UITextInput/NSTextInput`.
* Adds `rx_willDisplayCell` and `rx_didEndDisplayingCell` extensions to `UITableView`.
* Improves playgrounds.
#### Anomalies
* Fixes in documentation.
* Turns off Bitcode for `RxTests` CocoaPods integration.
* Fixes `UITextField.rx_text` and `UITextView.rx_text` integrations to be more robust when used with two way binding.
* Fixes two way binding example code so it now properly handles IME used in Asian cultures and adds explanations how to properly perform two way bindings. https://github.com/ReactiveX/RxSwift/issues/649
* Removes `distinctUntilChanged` from control extensions. https://github.com/ReactiveX/RxSwift/issues/626
## [2.4.0](https://github.com/ReactiveX/RxSwift/releases/tag/2.4)
#### Features
* adds `Driver.drive` with `Variable` parameter.
* exposes `RxSearchBarDelegateProxy`
* adds `rx_cancelButtonClicked` to `UISearchBar`.
* adds `rx_searchButtonClicked` to `UISearchBar`.
* adds `UISearchController` extensions:
* `rx_didDismiss`
* `rx_didPresent`
* `rx_present`
* `rx_willDismiss`
* `rx_willPresent`
#### Anomalies
* Fixes anomaly with `multicast` disposing subscription.
* Small grammar fixes in code.
* Fixes in documentation.
## [2.3.1](https://github.com/ReactiveX/RxSwift/releases/tag/2.3.1)
#### Features
@ -40,12 +143,12 @@ All notable changes to this project will be documented in this file.
This is example of those changes:
```swift
- public func rx_itemsWithCellFactory<S : SequenceType, O : ObservableType where O.E == S>
- public func rx_itemsWithCellFactory<S : Sequence, O : ObservableType where O.E == S>
(source: O)
(cellFactory: (UITableView, Int, S.Generator.Element) -> UITableViewCell) -> Disposable
+ public func rx_itemsWithCellFactory<S : SequenceType, O : ObservableType where O.E == S>
(cellFactory: (UITableView, Int, S.Iterator.Element) -> UITableViewCell) -> Disposable
+ public func rx_itemsWithCellFactory<S : Sequence, O : ObservableType where O.E == S>
(source: O)
-> (cellFactory: (UITableView, Int, S.Generator.Element) -> UITableViewCell) -> Disposable
-> (cellFactory: (UITableView, Int, S.Iterator.Element) -> UITableViewCell) -> Disposable
```
* Fixes anomaly in `CLLocationManager` extensions
@ -317,7 +420,7 @@ let (
* `NSURLSession` extensions now return `Observable<(NSData!, NSHTTPURLResponse)>` instead of `Observable<(NSData!, NSURLResponse!)>`.
* Optimizes consecutive map operators. For example `map(validate1).map(validate2).map(parse)` is now internally optimized to one `map` operator.
* Adds overloads for `just`, `sequenceOf`, `toObservable` that accept scheduler.
* Deprecates `asObservable` extension of `SequenceType` in favor of `toObservable`.
* Deprecates `asObservable` extension of `Sequence` in favor of `toObservable`.
* Adds `toObservable` extension to `Array`.
* Improves table view animated data source example.
* Polishing of `RxDataSourceStarterKit`
@ -429,7 +532,7 @@ let (
* Renames `ScopedDispose` to `ScopedDisposable`
* Deprecates `observeSingleOn` in favor of `observeOn`
* Adds inline documentation
* Renames `from` to `asObservable` extension method on `SequenceType`
* Renames `from` to `asObservable` extension method on `Sequence`
* Renames `catchErrorResumeNext` in favor of `catchErrorJustReturn`
* Deprecates `catchErrorToResult`, the preferred way is to use Swift `do/try/catch` mechanism.
* Deprecates `RxResult`, the preferred way is to use Swift `do/try/catch` mechanism.

74
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,74 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting one of the project maintainers https://github.com/ReactiveX/RxSwift/graphs/contributors. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

View File

@ -13,6 +13,14 @@ So what does this mean in practice:
* Please target your PR to **develop** branch
* If you want to make a bigger contribution to the project, please [open an issue first](https://github.com/ReactiveX/RxSwift/issues/new) so we can plan that work, discuss the architecture and brainstorm around that idea first.
## Submitting a Pull Request
Before submitting a pull request please make sure **`./scripts/all-tests.sh`** is passing (exits with 0), otherwise we won't be able to pull your code.
To be able to run `./scripts/all-tests.sh`, you'll need to install [xcpretty](https://github.com/supermarin/xcpretty).
`sudo gem install xcpretty`
## Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:

33
Dangerfile Normal file
View File

@ -0,0 +1,33 @@
# Warn about develop branch
current_branch = env.request_source.pr_json["base"]["ref"]
warn("Please target PRs to `develop` branch") if current_branch != "develop" && current_branch != "swift-3.0"
# Sometimes it's a README fix, or something like that - which isn't relevant for
# including in a project's CHANGELOG for example
declared_trivial = pr_title.include? "#trivial"
# Make it more obvious that a PR is a work in progress and shouldn't be merged yet
warn("PR is classed as Work in Progress") if pr_title.include? "[WIP]"
# Warn no CHANGELOG
warn("No CHANGELOG changes made") if lines_of_code > 50 && !modified_files.include?("CHANGELOG.yml") && !declared_trivial
# Warn pod spec changes
warn("RxCocoa.podspec changed") if modified_files.include?("RxCocoa.podspec")
warn("RxSwift.podspec changed") if modified_files.include?("RxSwift.podspec")
warn("RxTests.podspec changed") if modified_files.include?("RxTests.podspec")
warn("RxBlocking.podspec changed") if modified_files.include?("RxBlocking.podspec")
# Warn summary on pull request
if pr_body.length < 5
warn "Please provide a summary in the Pull Request description"
end
# If these are all empty something has gone wrong, better to raise it in a comment
if modified_files.empty? && added_files.empty? && deleted_files.empty?
fail "This PR has no changes at all, this is likely a developer issue."
end
# Warn when there is a big PR
warn("Big PR") if lines_of_code > 500

View File

@ -3,7 +3,7 @@ API
## RxSwift supported operators
In some cases there are multiple aliases for the same operator, because on different platforms / implementations, the same operation is sometimes called differently. Sometimes this is because historical reasons, sometimes because of reserved language keywords.
In some cases there are multiple aliases for the same operator, because on different platforms / implementations, the same operation is sometimes named differently. Sometimes this is because of historical reasons, while sometimes because of reserved language keywords.
When lacking a strong community consensus, RxSwift will usually include multiple aliases.
@ -26,6 +26,7 @@ Operators are stateless by default.
* [`timer`](http://reactivex.io/documentation/operators/timer.html)
#### Transforming Observables
* [`buffer`](http://reactivex.io/documentation/operators/buffer.html)
* [`flatMap`](http://reactivex.io/documentation/operators/flatmap.html)
* [`flatMapFirst`](http://reactivex.io/documentation/operators/flatmap.html)
@ -35,6 +36,7 @@ Operators are stateless by default.
* [`window`](http://reactivex.io/documentation/operators/window.html)
#### Filtering Observables
* [`debounce` / `throttle`](http://reactivex.io/documentation/operators/debounce.html)
* [`distinctUntilChanged`](http://reactivex.io/documentation/operators/distinct.html)
* [`elementAt`](http://reactivex.io/documentation/operators/elementat.html)
@ -71,6 +73,7 @@ Operators are stateless by default.
* debug
#### Conditional and Boolean Operators
* [`amb`](http://reactivex.io/documentation/operators/amb.html)
* [`skipWhile`](http://reactivex.io/documentation/operators/skipwhile.html)
* [`skipUntil`](http://reactivex.io/documentation/operators/skipuntil.html)
@ -99,13 +102,13 @@ Creating new operators is also pretty straightforward.
```swift
extension NSObject {
extension Reactive where Base: NSObject {
public var rx_deallocated: Observable<Void> {}
public var deallocated: Observable<Void> {}
#if !DISABLE_SWIZZLING
public var rx_deallocating: Observable<Void> {}
public var deallocating: Observable<Void> {}
#endif
@ -115,9 +118,9 @@ extension NSObject {
```swift
extension NSObject {
extension Reactive where Base: NSObject {
public func rx_observe<Element>(
public func observe<Element>(
type: E.Type,
_ keyPath: String,
options: NSKeyValueObservingOptions = .New | .Initial,
@ -126,7 +129,7 @@ extension NSObject {
#if !DISABLE_SWIZZLING
public func rx_observeWeakly<Element>(
public func observeWeakly<Element>(
type: E.Type,
_ keyPath: String,
options: NSKeyValueObservingOptions = .New | .Initial
@ -137,23 +140,23 @@ extension NSObject {
```
```swift
extension NSURLSession {
extension Reactive where Base: NSURLSession {
public func rx_response(request: NSURLRequest) -> Observable<(NSData, NSURLResponse)> {}
public func response(request: NSURLRequest) -> Observable<(NSData, NSURLResponse)> {}
public func rx_data(request: NSURLRequest) -> Observable<NSData> {}
public func data(request: NSURLRequest) -> Observable<NSData> {}
public func rx_JSON(request: NSURLRequest) -> Observable<AnyObject> {}
public func JSON(request: NSURLRequest) -> Observable<AnyObject> {}
public func rx_JSON(URL: NSURL) -> Observable<AnyObject> {}
public func JSON(URL: NSURL) -> Observable<AnyObject> {}
}
```
```swift
extension NSNotificationCenter {
extension Reactive where Base: NSNotificationCenter {
public func rx_notification(name: String, object: AnyObject?) -> Observable<NSNotification> {}
public func notification(name: String, object: AnyObject?) -> Observable<NSNotification> {}
}
```
@ -167,39 +170,39 @@ class DelegateProxy {
```
```swift
extension CLLocationManager {
extension Reactive where Base: CLLocationManager {
public var rx_delegate: DelegateProxy {}
public var delegate: DelegateProxy {}
public var rx_didUpdateLocations: Observable<[CLLocation]> {}
public var didUpdateLocations: Observable<[CLLocation]> {}
public var rx_didFailWithError: Observable<NSError> {}
public var didFailWithError: Observable<NSError> {}
public var rx_didFinishDeferredUpdatesWithError: Observable<NSError> {}
public var didFinishDeferredUpdatesWithError: Observable<NSError> {}
public var rx_didPauseLocationUpdates: Observable<Void> {}
public var didPauseLocationUpdates: Observable<Void> {}
public var rx_didResumeLocationUpdates: Observable<Void> {}
public var didResumeLocationUpdates: Observable<Void> {}
public var rx_didUpdateHeading: Observable<CLHeading> {}
public var didUpdateHeading: Observable<CLHeading> {}
public var rx_didEnterRegion: Observable<CLRegion> {}
public var didEnterRegion: Observable<CLRegion> {}
public var rx_didExitRegion: Observable<CLRegion> {}
public var didExitRegion: Observable<CLRegion> {}
public var rx_didDetermineStateForRegion: Observable<(state: CLRegionState, region: CLRegion)> {}
public var didDetermineStateForRegion: Observable<(state: CLRegionState, region: CLRegion)> {}
public var rx_monitoringDidFailForRegionWithError: Observable<(region: CLRegion?, error: NSError)> {}
public var monitoringDidFailForRegionWithError: Observable<(region: CLRegion?, error: NSError)> {}
public var rx_didStartMonitoringForRegion: Observable<CLRegion> {}
public var didStartMonitoringForRegion: Observable<CLRegion> {}
public var rx_didRangeBeaconsInRegion: Observable<(beacons: [CLBeacon], region: CLBeaconRegion)> {}
public var didRangeBeaconsInRegion: Observable<(beacons: [CLBeacon], region: CLBeaconRegion)> {}
public var rx_rangingBeaconsDidFailForRegionWithError: Observable<(region: CLBeaconRegion, error: NSError)> {}
public var rangingBeaconsDidFailForRegionWithError: Observable<(region: CLBeaconRegion, error: NSError)> {}
public var rx_didVisit: Observable<CLVisit> {}
public var didVisit: Observable<CLVisit> {}
public var rx_didChangeAuthorizationStatus: Observable<CLAuthorizationStatus> {}
public var didChangeAuthorizationStatus: Observable<CLAuthorizationStatus> {}
}
```
@ -208,258 +211,281 @@ extension CLLocationManager {
```swift
extension UIControl {
extension Reactive where Base: UIControl {
public func rx_controlEvent(controlEvents: UIControlEvents) -> ControlEvent<Void> {}
public func controlEvent(controlEvents: UIControlEvents) -> ControlEvent<Void> {}
public var rx_enabled: ObserverOf<Bool> {}
public var enabled: ObserverOf<Bool> {}
}
```
```swift
extension UIButton {
extension Reactive where Base: UIButton {
public var rx_tap: ControlEvent<Void> {}
public var tap: ControlEvent<Void> {}
}
```
```swift
extension UITextField {
extension Reactive where Base: UITextField {
public var rx_text: ControlProperty<String> {}
public var text: ControlProperty<String> {}
}
```
```swift
extension UITextView {
extension Reactive where Base: UITextView {
override func rx_createDelegateProxy() -> RxScrollViewDelegateProxy {}
override func createDelegateProxy() -> RxScrollViewDelegateProxy {}
public var rx_text: ControlProperty<String> {}
public var text: ControlProperty<String> {}
}
```
```swift
extension UISearchBar {
extension Reactive where Base: UISearchBar {
public var rx_delegate: DelegateProxy {}
public var delegate: DelegateProxy {}
public var rx_searchText: ControlProperty<String> {}
public var searchText: ControlProperty<String> {}
}
```
```swift
extension UILabel {
extension Reactive where Base: UILabel {
public var rx_text: ObserverOf<String> {}
public var text: ObserverOf<String> {}
}
```
```swift
extension UIDatePicker {
extension Reactive where Base: UIDatePicker {
public var rx_date: ControlProperty<NSDate> {}
public var date: ControlProperty<NSDate> {}
}
```
```swift
extension UIImageView {
extension Reactive where Base: UIImageView {
public var rx_image: ObserverOf<UIImage!> {}
public var image: ObserverOf<UIImage!> {}
public func rx_imageAnimated(transitionType: String?) -> AnyObserver<UIImage?>
public func imageAnimated(transitionType: String?) -> AnyObserver<UIImage?>
}
```
```swift
extension UIScrollView {
extension Reactive where Base: UIScrollView {
public var rx_delegate: DelegateProxy {}
public var delegate: DelegateProxy {}
public func rx_setDelegate(delegate: UIScrollViewDelegate) {}
public func setDelegate(delegate: UIScrollViewDelegate) {}
public var rx_contentOffset: ControlProperty<CGPoint> {}
public var contentOffset: ControlProperty<CGPoint> {}
}
```
```swift
extension UIBarButtonItem {
extension Reactive where Base: UIBarButtonItem {
public var rx_tap: ControlEvent<Void> {}
public var tap: ControlEvent<Void> {}
}
```
```swift
extension UISlider {
extension Reactive where Base: UISlider {
public var rx_value: ControlProperty<Float> {}
public var value: ControlProperty<Float> {}
}
```
```swift
extension UITableView {
extension Reactive where Base: UITableView {
public var rx_dataSource: DelegateProxy {}
public var dataSource: DelegateProxy {}
public func rx_setDataSource(dataSource: UITableViewDataSource) -> Disposable {}
public func setDataSource(dataSource: UITableViewDataSource) -> Disposable {}
public func rx_itemsWithCellFactory(source: O)(cellFactory: (UITableView, Int, S.Generator.Element) -> UITableViewCell) -> Disposable {}
public func itemsWithCellFactory(source: O)(cellFactory: (UITableView, Int, S.Iterator.Element) -> UITableViewCell) -> Disposable {}
public func rx_itemsWithCellIdentifier(cellIdentifier: String, cellType: Cell.Type = Cell.self)(source: O)(configureCell: (Int, S.Generator.Element, Cell) -> Void) -> Disposable {}
public func itemsWithCellIdentifier(cellIdentifier: String, cellType: Cell.Type = Cell.self)(source: O)(configureCell: (Int, S.Iterator.Element, Cell) -> Void) -> Disposable {}
public func rx_itemsWithDataSource(dataSource: DataSource)(source: O) -> Disposable {}
public func itemsWithDataSource(dataSource: DataSource)(source: O) -> Disposable {}
public var rx_itemSelected: ControlEvent<NSIndexPath> {}
public var itemSelected: ControlEvent<IndexPath> {}
public var rx_itemDeselected: ControlEvent<NSIndexPath> {}
public var itemDeselected: ControlEvent<IndexPath> {}
public var rx_itemInserted: ControlEvent<NSIndexPath> {}
public var itemInserted: ControlEvent<IndexPath> {}
public var rx_itemDeleted: ControlEvent<NSIndexPath> {}
public var itemDeleted: ControlEvent<IndexPath> {}
public var rx_itemMoved: ControlEvent<ItemMovedEvent> {}
public var itemMoved: ControlEvent<ItemMovedEvent> {}
// This method only works in case one of the `rx_itemsWith*` methods was used, or data source implements `SectionedViewDataSourceType`
public func rx_modelSelected<T>(modelType: T.Type) -> ControlEvent<T> {}
// This method only works in case one of the `rx.itemsWith*` methods was used, or data source implements `SectionedViewDataSourceType`
public func modelSelected<T>(modelType: T.Type) -> ControlEvent<T> {}
// This method only works in case one of the `rx_itemsWith*` methods was used, or data source implements `SectionedViewDataSourceType`
public func rx_modelDeselected<T>(modelType: T.Type) -> ControlEvent<T> {}
// This method only works in case one of the `rx.itemsWith*` methods was used, or data source implements `SectionedViewDataSourceType`
public func modelDeselected<T>(modelType: T.Type) -> ControlEvent<T> {}
}
```
```swift
extension UICollectionView {
extension Reactive where Base: UICollectionView {
public var rx_dataSource: DelegateProxy {}
public var dataSource: DelegateProxy {}
public func rx_setDataSource(dataSource: UICollectionViewDataSource) -> Disposable {}
public func setDataSource(dataSource: UICollectionViewDataSource) -> Disposable {}
public func rx_itemsWithCellFactory(source: O)(cellFactory: (UICollectionView, Int, S.Generator.Element) -> UICollectionViewCell) -> Disposable {}
public func itemsWithCellFactory(source: O)(cellFactory: (UICollectionView, Int, S.Iterator.Element) -> UICollectionViewCell) -> Disposable {}
public func rx_itemsWithCellIdentifier(cellIdentifier: String, cellType: Cell.Type = Cell.self)(source: O)(configureCell: (Int, S.Generator.Element, Cell) -> Void) -> Disposable {}
public func itemsWithCellIdentifier(cellIdentifier: String, cellType: Cell.Type = Cell.self)(source: O)(configureCell: (Int, S.Iterator.Element, Cell) -> Void) -> Disposable {}
public func rx_itemsWithDataSource(dataSource: DataSource)(source: O) -> Disposable {}
public func itemsWithDataSource(dataSource: DataSource)(source: O) -> Disposable {}
public var rx_itemSelected: ControlEvent<NSIndexPath> {}
public var itemSelected: ControlEvent<IndexPath> {}
public var rx_itemDeselected: ControlEvent<NSIndexPath> {}
public var itemDeselected: ControlEvent<IndexPath> {}
// This method only works in case one of the `rx_itemsWith*` methods was used, or data source implements `SectionedViewDataSourceType`
public func rx_modelSelected<T>(modelType: T.Type) -> ControlEvent<T> {}
// This method only works in case one of the `rx.itemsWith*` methods was used, or data source implements `SectionedViewDataSourceType`
public func modelSelected<T>(modelType: T.Type) -> ControlEvent<T> {}
// This method only works in case one of the `rx_itemsWith*` methods was used, or data source implements `SectionedViewDataSourceType`
public func rx_modelSelected<T>(modelType: T.Type) -> ControlEvent<T> {}
// This method only works in case one of the `rx.itemsWith*` methods was used, or data source implements `SectionedViewDataSourceType`
public func modelSelected<T>(modelType: T.Type) -> ControlEvent<T> {}
}
```
```swift
extension UIGestureRecognizer {
extension Reactive where Base: UIGestureRecognizer {
public var rx_event: ControlEvent<UIGestureRecognizer> {}
public var event: ControlEvent<UIGestureRecognizer> {}
}
```
```swift
extension UIImagePickerController {
extension Reactive where Base: UIImagePickerController {
public var rx_didFinishPickingMediaWithInfo: Observable<[String : AnyObject]> {}
public var didFinishPickingMediaWithInfo: Observable<[String : AnyObject]> {}
public var rx_didCancel: Observable<()> {}
public var didCancel: Observable<()> {}
}
```
```swift
extension UISegmentedControl {
extension Reactive where Base: UISegmentedControl {
public var rx_value: ControlProperty<Int> {}
public var value: ControlProperty<Int> {}
}
```
```swift
extension UISwitch {
extension Reactive where Base: UISwitch {
public var rx_value: ControlProperty<Bool> {}
public var value: ControlProperty<Bool> {}
}
```
```swift
extension UIActivityIndicatorView {
extension Reactive where Base: UIActivityIndicatorView {
public var rx_animating: AnyObserver<Bool> {}
public var animating: AnyObserver<Bool> {}
}
```
```swift
extension Reactive where Base: UINavigationItem {
public var title: AnyObserver<String?> {}
}
```
**OSX**
```swift
extension NSControl {
extension Reactive where Base: NSControl {
public var rx_controlEvent: ControlEvent<()> {}
public var controlEvent: ControlEvent<()> {}
public var rx_enabled: AnyObserver<Bool> {}
public var enabled: AnyObserver<Bool> {}
}
```
```swift
extension NSSlider {
extension Reactive where Base: NSSlider {
public var rx_value: ControlProperty<Double> {}
public var value: ControlProperty<Double> {}
}
```
```swift
extension NSButton {
extension Reactive where Base: NSButton {
public var rx_tap: ControlEvent<Void> {}
public var tap: ControlEvent<Void> {}
public var rx_state: ControlProperty<Int> {}
public var state: ControlProperty<Int> {}
}
```
```swift
extension NSImageView {
extension Reactive where Base: NSImageView {
public var rx_image: ObserverOf<NSImage?> {}
public var image: ObserverOf<NSImage?> {}
public func rx_imageAnimated(transitionType: String?) -> AnyObserver<NSImage?>
public func imageAnimated(transitionType: String?) -> AnyObserver<NSImage?>
}
```
```swift
extension NSTextField {
extension Reactive where Base: NSTextField {
public var rx_delegate: DelegateProxy {}
public var delegate: DelegateProxy {}
public var rx_text: ControlProperty<String> {}
public var text: ControlProperty<String> {}
}
```
```swift
extension UITabBarItem {
extension Reactive where Base: UITabBarItem {
public var rx_badgeValue: AnyObserver<String?> {}
public var badgeValue: AnyObserver<String?> {}
}
```
```swift
extension Reactive where Base: UITabBar {
public var didSelectItem: ControlEvent<UITabBarItem> {}
public var willBeginCustomizing: ControlEvent<[UITabBarItem]> {}
public var didBeginCustomizing: ControlEvent<[UITabBarItem]> {}
public var willEndCustomizing: ControlEvent<(items: [UITabBarItem], changed: Bool)> {}
public var didEndCustomizing: ControlEvent<(items: [UITabBarItem], changed: Bool)> {}
}
```

View File

@ -2,18 +2,18 @@
RxSwift is somewhat similar to ReactiveCocoa since ReactiveCocoa borrows a large number of concepts from Rx.
One of the main goals of this project was to create a significantly simpler interface that is more aligned with other Rx implementations, offers richer concurrency model, offers more optimization opportunities and is more aligned with built-in Swift error handling mechanisms.
One of the main goals of this project was to create a significantly simpler interface that is more aligned with other Rx implementations, offers a richer concurrency model, offers more optimization opportunities and is more aligned with built-in Swift error handling mechanisms.
We've also decided to only rely on Swift/llvm compiler and not introduce any external dependencies.
We've also decided to only rely on the Swift/llvm compiler and not introduce any external dependencies.
Probably the main difference between these projects is the difference of approach in building abstractions.
Probably the main difference between these projects is in their approach in building abstractions.
The main goal of RxSwift project is to provide environment agnostic compositional computation glue abstracted in the form of observable sequences.
We then aim to improve the experience of using RxSwift on specific platforms. To do this RxCocoa uses those generic computations to build more practical abstractions and wrap Foundation/Cocoa/UKit frameworks. That means that other libraries give context and semantics to the generic computation engine RxSwift provides such as `Driver`, `ControlProperty`, `ControlEvent`s and more.
We then aim to improve the experience of using RxSwift on specific platforms. To do this, RxCocoa uses generic computations to build more practical abstractions and wrap Foundation/Cocoa/UKit frameworks. That means that other libraries give context and semantics to the generic computation engine RxSwift provides such as `Driver`, `ControlProperty`, `ControlEvent`s and more.
One of the benefits to representing all these abstractions as a single concept; _observable sequences_, is that all computation abstractions built on top of them are also composable in the same fundamental way. They all follow the same contract and implement the same interface.
One of the benefits to representing all of these abstractions as a single concept - _observable sequences_ - is that all computation abstractions built on top of them are also composable in the same fundamental way. They all follow the same contract and implement the same interface.
It is also easy to create flexible subscription (resource) sharing strategies or use one of the built-in ones: `share`, `shareReplay`, `publish`, `multicast`, `shareReplayLatestWhileConnected`...
This library also offers fine-tunable concurrency model. In case concurrent schedulers are used, observable sequence operators will preserve sequence properties. The same observable sequence operators will also know how to detect and optimally use known serial schedulers. ReactiveCocoa has a more limited concurrency model and only allows serial schedulers.
This library also offers a fine-tunable concurrency model. If concurrent schedulers are used, observable sequence operators will preserve sequence properties. The same observable sequence operators will also know how to detect and optimally use known serial schedulers. ReactiveCocoa has a more limited concurrency model and only allows serial schedulers.
Multithreaded programming is really hard and detecting non trivial loops is even harder. That's why all operators are built in a fault tolerant way. Even in case element generation occurs during element processing (recursion), operators will try to handle that situation and prevent deadlocks. That means that in worst possible case programming error will cause stack overflow, but users won't have to manually kill the app, and you will get crash report in error reporting systems so you can find and fix the problem.
Multithreaded programming is really hard and detecting non trivial loops is even harder. That's why all operators are built in a fault tolerant way. Even if element generation occurs during element processing (recursion), operators will try to handle that situation and prevent deadlocks. This means that in the worst possible case programming error will cause stack overflow, but users won't have to manually kill the app, and you will get a crash report in error reporting systems so you can find and fix the problem.

View File

@ -11,29 +11,29 @@ enum Event<Element> {
}
```
Let's discuss pros and cons of `ErrorType` being generic.
Let's discuss the pros and cons of `ErrorType` being generic.
If you have generic error type you create additional impedance mismatch between two observables.
If you have a generic error type, you create additional impedance mismatch between two observables.
Let's say you have:
`Observable<String, E1>` and `Observable<String, E2>`
There isn't much you can do with them without figuring out what will be the resulting error type.
There isn't much you can do with them without figuring out what the resulting error type will be.
Will it be `E1`, `E2` or some new `E3` maybe? So you need a new set of operators just to solve that impedance mismatch.
Will it be `E1`, `E2` or some new `E3` maybe? So, you would need a new set of operators just to solve that impedance mismatch.
This for sure hurts composition properties, and Rx really doesn't care about why sequence fails, it just usually forwards failure further down the observable chain.
This hurts composition properties, and Rx isn't concerned with why a sequence fails, it just usually forwards failures further down the observable chain.
There is additional problem that maybe in some cases operators will fail for some internal error, and in that case you won't be able to construct resulting error and report failure.
There is an additional problem that, in some cases, operators might fail due to some internal error, in which case you wouldn't be able to construct a resulting error and report failure.
But ok, let's ignore that and assume we can use that to model sequences that don't error out. It looks like it could be useful for that purpose?
But OK, let's ignore that and assume we can use that to model sequences that don't error out. Could it be useful for that purpose?
Well yes, it potentially could be, but lets consider why would you want to use sequences that don't error out.
Well yes, it potentially could be, but let's consider why you would want to use sequences that don't error out.
One obvious application would be for permanent streams in UI layer that drive entire UI. But when you consider that case, it's not really only sufficient to use compiler to prove that sequences don't error out, you also need to prove other properties. Like that elements are observed on `MainScheduler`.
One obvious application would be for permanent streams in the UI layer that drive the entire UI. When you consider that case, it's not really sufficient to only use the compiler to prove that sequences don't error out, you also need to prove other properties. For instance, that elements are observed on `MainScheduler`.
What you really need is a generic way to prove traits for sequences (`Observables`). And you could be interested in a lot of properties. For example:
What you really need is a generic way to prove traits for observable sequences. There are a lot of properties you could be interested in. For example:
* sequence terminates in finite time (server side)
* sequence contains only one element (if you are running some computation)
@ -41,19 +41,19 @@ What you really need is a generic way to prove traits for sequences (`Observable
* sequence doesn't error out, never terminates and elements are delivered on main scheduler, and has refcounted sharing (UI)
* sequence doesn't error out, never terminates and elements are delivered on specific background scheduler (audio engine)
What you really want is a general compiler enforced system of traits for observable sequences, and a set of invariant operators for those wanted properties.
What you really want is a general compiler-enforced system of traits for observable sequences, and a set of invariant operators for those wanted properties.
A good analogy IMHO would be
A good analogy would be:
```
1, 3.14, e, 2.79, 1 + 1i <-> Observable<E>
1m/s, 1T, 5kg, 1.3 pounds <-> Errorless observable, UI observable, Finite observable ...
```
There are many ways how to do that in Swift by either using composition or inheritance of observables.
There are many ways to do such a thing in Swift by either using composition or inheritance of observables.
Additional benefit of using unit system is that you can prove that UI code is executing on same scheduler and thus use lockless operators for all transformations.
An additional benefit of using a unit system is that you can prove that UI code is executing on the same scheduler and thus use lockless operators for all transformations.
Since Rx already doesn't have locks for single sequence operations, and all of the remaining locks are in statefull components (aka UI), that would practically remove all of the remaining locks out of Rx code and create compiler enforced lockless Rx code.
Since RxSwift already doesn't have locks for single sequence operations, and all of the locks that do exist are in stateful components (e.g. UI), there are practically no locks in RxSwift code, which allows for such details to be compiler enforced.
So IMHO, there really is no benefit of using typed Errors that couldn't be achieved cleaner in other ways while preserving Rx compositional semantics. And other ways also have huge other benefits.
There really is no benefit to using typed Errors that couldn't be achieved in other cleaner ways while preserving Rx compositional semantics.

View File

@ -9,92 +9,82 @@ Examples
## Calculated variable
Let's first start with some imperative swift code.Sw
The purpose of example is to bind identifier `c` to a value calculated from `a` and `b` if some condition is satisfied.
First, let's start with some imperative code.
The purpose of this example is to bind the identifier `c` to a value calculated from `a` and `b` if some condition is satisfied.
Here is the imperative swift code that calculates the value of `c`:
Here is the imperative code that calculates the value of `c`:
```swift
// this is usual imperative code
// this is standard imperative code
var c: String
var a = 1 // this will only assign value `1` to `a` once
var b = 2 // this will only assign value `2` to `b` once
var a = 1 // this will only assign the value `1` to `a` once
var b = 2 // this will only assign the value `2` to `b` once
if a + b >= 0 {
c = "\(a + b) is positive" // this will only assign value to `c` once
c = "\(a + b) is positive" // this will only assign the value to `c` once
}
```
The value of `c` is now `3 is positive`. But if we change the value of `a` to `4`, `c` will still contain the old value.
The value of `c` is now `3 is positive`. However, if we change the value of `a` to `4`, `c` will still contain the old value.
```swift
a = 4 // c will still be equal "3 is positive" which is not good
// c should be equal to "6 is positive" because 4 + 2 = 6
a = 4 // `c` will still be equal to "3 is positive" which is not good
// we want `c` to be equal to "6 is positive" since 4 + 2 = 6
```
This is not the wanted behavior.
This is not the desired behavior.
To integrate RxSwift framework into your project just include framework in your project and write `import RxSwift`.
This is the same logic using RxSwift.
This is the improved logic using RxSwift:
```swift
let a /*: Observable<Int>*/ = Variable(1) // a = 1
let b /*: Observable<Int>*/ = Variable(2) // b = 2
// This will "bind" rx variable `c` to definition
// if a + b >= 0 {
// c = "\(a + b) is positive"
// }
// combines latest values of variables `a` and `b` using `+`
let c = Observable.combineLatest(a.asObservable(), b.asObservable()) { $0 + $1 }
.filter { $0 >= 0 } // if `a + b >= 0` is true, `a + b` is passed to map operator
.filter { $0 >= 0 } // if `a + b >= 0` is true, `a + b` is passed to the map operator
.map { "\($0) is positive" } // maps `a + b` to "\(a + b) is positive"
// Since initial values are a = 1, b = 2
// 1 + 2 = 3 which is >= 0, `c` is intially equal to "3 is positive"
// Since the initial values are a = 1 and b = 2
// 1 + 2 = 3 which is >= 0, so `c` is initially equal to "3 is positive"
// To pull values out of rx variable `c`, subscribe to values from `c`.
// `subscribeNext` means subscribe to next (fresh) values of variable `c`.
// That also includes the inital value "3 is positive".
c.subscribeNext { print($0) } // prints: "3 is positive"
// To pull values out of the Rx `Observable` `c`, subscribe to values from `c`.
// `subscribe(onNext:)` means subscribe to the next (fresh) values of `c`.
// That also includes the initial value "3 is positive".
c.subscribe(onNext: { print($0) }) // prints: "3 is positive"
// Now let's increase the value of `a`
// a = 4 is in RxSwift
// Now, let's increase the value of `a`
a.value = 4 // prints: 6 is positive
// Sum of latest values is now `4 + 2`, `6` is >= 0, map operator
// produces "6 is positive" and that result is "assigned" to `c`.
// The sum of the latest values, `4` and `2`, is now `6`.
// Since this is `>= 0`, the `map` operator produces "6 is positive"
// and that result is "assigned" to `c`.
// Since the value of `c` changed, `{ print($0) }` will get called,
// and "6 is positive" is printed.
// and "6 is positive" will be printed.
// Now let's change the value of `b`
// b = -8 is in RxSwift
// Now, let's change the value of `b`
b.value = -8 // doesn't print anything
// Sum of latest values is `4 + (-8)`, `-4` is not >= 0, map doesn't
// get executed.
// That means that `c` still contains "6 is positive" and that's correct.
// Since `c` hasn't been updated, that means next value hasn't been produced,
// The sum of the latest values, `4 + (-8)`, is `-4`.
// Since this is not `>= 0`, `map` doesn't get executed.
// This means that `c` still contains "6 is positive"
// Since `c` hasn't been updated, a new "next" value hasn't been produced,
// and `{ print($0) }` won't be called.
// ...
```
## Simple UI bindings
* instead of binding to variables, let's bind to text field values (rx_text)
* next, parse that into an int and calculate if the number is prime using an async API (map)
* if text field value is changed before async call completes, new async call will be enqueued (concat)
* bind results to label (bindTo(resultLabel.rx_text))
* Instead of binding to variables, let's bind to `UITextField` values using the `rx.text` property
* Next, `map` the `String` into an `Int` and determine if the number is prime using an async API
* If the text is changed before the async call completes, a new async call will replace it via `concat`
* Bind the results to a `UILabel`
```swift
let subscription/*: Disposable */ = primeTextField.rx_text // type is Observable<String>
.map { WolframAlphaIsPrime(Int($0) ?? 0) } // type is Observable<Observable<Prime>>
let subscription/*: Disposable */ = primeTextField.rx.text // type is Observable<String>
.map { WolframAlphaIsPrime(Int($0) ?? 0) } // type is Observable<Observable<Prime>>
.concat() // type is Observable<Prime>
.map { "number \($0.n) is prime? \($0.isPrime)" } // type is Observable<String>
.bindTo(resultLabel.rx_text) // return Disposable that can be used to unbind everything
.bindTo(resultLabel.rx.text) // return Disposable that can be used to unbind everything
// This will set resultLabel.text to "number 43 is prime? true" after
// This will set `resultLabel.text` to "number 43 is prime? true" after
// server call completes.
primeTextField.text = "43"
@ -104,13 +94,13 @@ primeTextField.text = "43"
subscription.dispose()
```
All of the operators used in this example are the same operators used in the first example with variables. Nothing special about it.
All of the operators used in this example are the same operators used in the first example with variables. There's nothing special about it.
## Autocomplete
If you are new to Rx, next example will probably be a little overwhelming, but it's here to demonstrate how RxSwift code looks like in real world examples.
If you are new to Rx, the next example will probably be a little overwhelming at first. However, it's here to demonstrate how RxSwift code looks in the real-world.
The third example is a real world, complex UI async validation logic, with progress notifications.
This example contains complex async UI validation logic with progress notifications.
All operations are cancelled the moment `disposeBag` is deallocated.
Let's give it a shot.
@ -118,31 +108,31 @@ Let's give it a shot.
```swift
// bind UI control values directly
// use username from `usernameOutlet` as username values source
self.usernameOutlet.rx_text
self.usernameOutlet.rx.text
.map { username in
// synchronous validation, nothing special here
if username.isEmpty {
// Convenience for constructing synchronous result.
// In case there is mixed synchronous and asychronous code inside the same
// method, this will construct an async result that is resolved immediatelly.
// In case there is mixed synchronous and asynchronous code inside the same
// method, this will construct an async result that is resolved immediately.
return Observable.just((valid: false, message: "Username can't be empty."))
}
...
// ...
// Every user interface probably shows some state while async operation
// is executing.
// Let's assume that we want to show "Checking availability" while waiting for result.
// valid parameter can be
// User interfaces should probably show some state while async operations
// are executing.
// Let's assume that we want to show "Checking availability" while waiting for a result.
// Valid parameters can be:
// * true - is valid
// * false - not valid
// * false - is not valid
// * nil - validation pending
typealias LoadingInfo = (valid : String?, message: String?)
typealias LoadingInfo = (valid: String?, message: String?)
let loadingValue : LoadingInfo = (valid: nil, message: "Checking availability ...")
// This will fire a server call to check if the username already exists.
// Guess what, its type is `Observable<ValidationResult>`
// Its type is `Observable<ValidationResult>`
return API.usernameAvailable(username)
.map { available in
if available {
@ -156,26 +146,25 @@ self.usernameOutlet.rx_text
.startWith(loadingValue)
}
// Since we now have `Observable<Observable<ValidationResult>>`
// we somehow need to return to normal `Observable` world.
// We could use `concat` operator from second example, but we really
// want to cancel pending asynchronous operation if new username is
// provided.
// That's what `switchLatest` does
// we need to somehow return to a simple `Observable<ValidationResult>`.
// We could use the `concat` operator from the second example, but we really
// want to cancel pending asynchronous operations if a new username is provided.
// That's what `switchLatest` does.
.switchLatest()
// Now we need to bind that to the user interface somehow.
// Good old `subscribeNext` can do that
// Good old `subscribe(onNext:)` can do that.
// That's the end of `Observable` chain.
// This will produce a `Disposable` object that can unbind everything and cancel
// pending async operations.
.subscribeNext { valid in
.subscribe(onNext: { valid in
errorLabel.textColor = validationColor(valid)
errorLabel.text = valid.message
}
// Why would we do it manually, that's tedious,
// let's dispose everything automagically on view controller dealloc.
})
// This will produce a `Disposable` object that can unbind everything and cancel
// pending async operations.
// Instead of doing it manually, which is tedious,
// let's dispose everything automagically upon view controller dealloc.
.addDisposableTo(disposeBag)
```
Can't get any simpler than this. There are [more examples](../RxExample) in the repository, so feel free to check them out.
It doesn't get any simpler than that. There are [more examples](../RxExample) in the repository, so feel free to check them out.
They include examples on how to use it in the context of MVVM pattern or without it.
They include examples on how to use Rx in the context of MVVM pattern or without it.

View File

@ -26,11 +26,13 @@ This project tries to be consistent with [ReactiveX.io](http://reactivex.io/). T
# Observables aka Sequences
## Basics
The [Equivalence](MathBehindRx.md) of observer patterns (`Observable<Element>`) and sequences (`Generator`s)
is one of the most important things to understand about Rx.
The [equivalence](MathBehindRx.md) of observer pattern (`Observable<Element>` sequence) and normal sequences (`SequenceType`) is the most important thing to understand about Rx.
The observer pattern is needed because we want to model asynchronous behavior.
That equivalence enables the implementation of high level sequence operations as operators on `Observable`s.
**Every `Observable` sequence is just a sequence. The key advantage for an `Observable` vs Swift's `SequenceType` is that it can also receive elements asynchronously. This is the kernel of the RxSwift, documentation from here is about ways that we expand on that idea.**
* `Observable`(`ObservableType`) is equivalent to `SequenceType`
* `ObservableType.subscribe` method is equivalent to `SequenceType.generate` method.
* Observer (callback) needs to be passed to `ObservableType.subscribe` method to receive sequence elements instead of calling `next()` on the returned generator.
Sequences are a simple, familiar concept that is **easy to visualize**.
@ -65,32 +67,32 @@ These are called marble diagrams. There are more marble diagrams at [rxmarbles.c
If we were to specify sequence grammar as a regular expression it would look like:
**Next* (Error | Completed)?**
**next* (error | completed)?**
This describes the following:
* **Sequences can have 0 or more elements.**
* **Once an `Error` or `Completed` event is received, the sequence cannot produce any other element.**
* **Once an `error` or `completed` event is received, the sequence cannot produce any other element.**
Sequences in Rx are described by a push interface (aka callback).
```swift
enum Event<Element> {
case Next(Element) // next element of a sequence
case Error(ErrorType) // sequence failed with error
case Completed // sequence terminated successfully
case next(Element) // next element of a sequence
case error(Swift.Error) // sequence failed with error
case completed // sequence terminated successfully
}
class Observable<Element> {
func subscribe(observer: Observer<Element>) -> Disposable
func subscribe(_ observer: Observer<Element>) -> Disposable
}
protocol ObserverType {
func on(event: Event<Element>)
func on(_ event: Event<Element>)
}
```
**When a sequence sends the `Complete` or `Error` event all internal resources that compute sequence elements will be freed.**
**When a sequence sends the `completed` or `error` event all internal resources that compute sequence elements will be freed.**
**To cancel production of sequence elements and free resources immediately, call `dispose` on the returned subscription.**
@ -100,7 +102,7 @@ If a sequence does not terminate in some way, resources will be allocated perman
**Using dispose bags or `takeUntil` operator is a robust way of making sure resources are cleaned up. We recommend using them in production even if the sequences will terminate in finite time.**
In case you are curious why `ErrorType` isn't generic, you can find explanation [here](DesignRationale.md#why-error-type-isnt-generic).
In case you are curious why `Swift.Error` isn't generic, you can find explanation [here](DesignRationale.md#why-error-type-isnt-generic).
## Disposing
@ -114,7 +116,7 @@ let subscription = Observable<Int>.interval(0.3, scheduler: scheduler)
print(event)
}
NSThread.sleepForTimeInterval(2)
NSThread.sleep(forTimeInterval: 2.0)
subscription.dispose()
@ -131,7 +133,7 @@ This will print:
5
```
Note the you usually do not want to manually call `dispose`; this is only educational example. Calling dispose manually is usually a bad code smell. There are better ways to dispose subscriptions. We can use `DisposeBag`, the `takeUntil` operator, or some other mechanism.
Note that you usually do not want to manually call `dispose`; this is only educational example. Calling dispose manually is usually a bad code smell. There are better ways to dispose subscriptions. We can use `DisposeBag`, the `takeUntil` operator, or some other mechanism.
So can this code print something after the `dispose` call executed? The answer is: it depends.
@ -206,7 +208,7 @@ Additional way to automatically dispose subscription on dealloc is to use `takeU
```swift
sequence
.takeUntil(self.rx_deallocated)
.takeUntil(self.rx.deallocated)
.subscribe {
print($0)
}
@ -216,9 +218,9 @@ sequence
There is also a couple of additional guarantees that all sequence producers (`Observable`s) must honor.
It doesn't matter on which thread they produce elements, but if they generate one element and send it to the observer `observer.on(.Next(nextElement))`, they can't send next element until `observer.on` method has finished execution.
It doesn't matter on which thread they produce elements, but if they generate one element and send it to the observer `observer.on(.next(nextElement))`, they can't send next element until `observer.on` method has finished execution.
Producers also cannot send terminating `.Completed` or `.Error` in case `.Next` event hasn't finished.
Producers also cannot send terminating `.completed` or `.error` in case `.next` event hasn't finished.
In short, consider this example:
@ -274,9 +276,9 @@ let searchForMe = searchWikipedia("me")
let cancel = searchForMe
// sequence generation starts now, URL requests are fired
.subscribeNext { results in
.subscribe(onNext: { results in
print(results)
}
})
```
@ -289,16 +291,16 @@ Let's create a function which creates a sequence that returns one element upon s
```swift
func myJust<E>(element: E) -> Observable<E> {
return Observable.create { observer in
observer.on(.Next(element))
observer.on(.Completed)
return NopDisposable.instance
observer.on(.next(element))
observer.on(.completed)
return Disposables.create()
}
}
myJust(0)
.subscribeNext { n in
.subscribe(onNext: { n in
print(n)
}
})
```
this will print:
@ -323,11 +325,11 @@ Lets now create an observable that returns elements from an array.
func myFrom<E>(sequence: [E]) -> Observable<E> {
return Observable.create { observer in
for element in sequence {
observer.on(.Next(element))
observer.on(.next(element))
}
observer.on(.Completed)
return NopDisposable.instance
observer.on(.completed)
return Disposables.create()
}
}
@ -337,17 +339,17 @@ print("Started ----")
// first time
stringCounter
.subscribeNext { n in
.subscribe(onNext: { n in
print(n)
}
})
print("----")
// again
stringCounter
.subscribeNext { n in
.subscribe(onNext: { n in
print(n)
}
})
print("Ended ----")
```
@ -380,15 +382,15 @@ func myInterval(interval: NSTimeInterval) -> Observable<Int> {
var next = 0
dispatch_source_set_timer(timer, 0, UInt64(interval * Double(NSEC_PER_SEC)), 0)
let cancel = AnonymousDisposable {
let cancel = Disposables.create {
print("Disposed")
dispatch_source_cancel(timer)
}
dispatch_source_set_event_handler(timer, {
if cancel.disposed {
if cancel.isDisposed {
return
}
observer.on(.Next(next))
observer.on(.next(next))
next += 1
})
dispatch_resume(timer)
@ -404,11 +406,12 @@ let counter = myInterval(0.1)
print("Started ----")
let subscription = counter
.subscribeNext { n in
.subscribe(onNext: { n in
print(n)
}
})
NSThread.sleepForTimeInterval(0.5)
NSThread.sleep(forTimeInterval: 0.5)
subscription.dispose()
@ -436,19 +439,19 @@ let counter = myInterval(0.1)
print("Started ----")
let subscription1 = counter
.subscribeNext { n in
.subscribe(onNext: { n in
print("First \(n)")
}
})
let subscription2 = counter
.subscribeNext { n in
.subscribe(onNext: { n in
print("Second \(n)")
}
})
NSThread.sleepForTimeInterval(0.5)
NSThread.sleep(forTimeInterval: 0.5)
subscription1.dispose()
NSThread.sleepForTimeInterval(0.5)
NSThread.sleep(forTimeInterval: 0.5)
subscription2.dispose()
@ -501,13 +504,13 @@ let counter = myInterval(0.1)
print("Started ----")
let subscription1 = counter
.subscribeNext { n in
.subscribe(onNext: { n in
print("First \(n)")
}
})
let subscription2 = counter
.subscribeNext { n in
.subscribe(onNext: { n in
print("Second \(n)")
}
})
NSThread.sleepForTimeInterval(0.5)
@ -552,27 +555,27 @@ Behavior for URL observables is equivalent.
This is how HTTP requests are wrapped in Rx. It's pretty much the same pattern like the `interval` operator.
```swift
extension NSURLSession {
public func rx_response(request: NSURLRequest) -> Observable<(NSData, NSURLResponse)> {
extension Reactive where Base: NSURLSession {
public func response(request: NSURLRequest) -> Observable<(NSData, NSURLResponse)> {
return Observable.create { observer in
let task = self.dataTaskWithRequest(request) { (data, response, error) in
guard let response = response, data = data else {
observer.on(.Error(error ?? RxCocoaURLError.Unknown))
observer.on(.error(error ?? RxCocoaURLError.Unknown))
return
}
guard let httpResponse = response as? NSHTTPURLResponse else {
observer.on(.Error(RxCocoaURLError.NonHTTPResponse(response: response)))
observer.on(.error(RxCocoaURLError.nonHTTPResponse(response: response)))
return
}
observer.on(.Next(data, httpResponse))
observer.on(.Completed)
observer.on(.next(data, httpResponse))
observer.on(.completed)
}
task.resume()
return AnonymousDisposable {
return Disposables.create {
task.cancel()
}
}
@ -590,7 +593,7 @@ Almost all operators are demonstrated in [Playgrounds](../Rx.playground).
To use playgrounds please open `Rx.xcworkspace`, build `RxSwift-OSX` scheme and then open playgrounds in `Rx.xcworkspace` tree view.
In case you need an operator, and don't know how to find it there a [decision tree of operators]() http://reactivex.io/documentation/operators.html#tree).
In case you need an operator, and don't know how to find it there a [decision tree of operators](http://reactivex.io/documentation/operators.html#tree).
[Supported RxSwift operators](API.md#rxswift-supported-operators) are also grouped by function they perform, so that can also help.
@ -612,13 +615,13 @@ extension ObservableType {
return Observable.create { observer in
let subscription = self.subscribe { e in
switch e {
case .Next(let value):
case .next(let value):
let result = transform(value)
observer.on(.Next(result))
case .Error(let error):
observer.on(.Error(error))
case .Completed:
observer.on(.Completed)
observer.on(.next(result))
case .error(let error):
observer.on(.error(error))
case .completed:
observer.on(.completed)
}
}
@ -635,9 +638,9 @@ let subscription = myInterval(0.1)
.myMap { e in
return "This is simply \(e)"
}
.subscribeNext { n in
.subscribe(onNext: { n in
print(n)
}
})
```
and this will print
@ -666,9 +669,9 @@ This isn't something that should be practiced often, and is a bad code smell, bu
let magicBeings: Observable<MagicBeing> = summonFromMiddleEarth()
magicBeings
.subscribeNext { being in // exit the Rx monad
.subscribe(onNext: { being in // exit the Rx monad
self.doSomeStateMagic(being)
}
})
.addDisposableTo(disposeBag)
//
@ -678,7 +681,7 @@ This isn't something that should be practiced often, and is a bad code smell, bu
being,
UIApplication.delegate.dataSomething.attendees
)
kittens.on(.Next(kitten)) // send result back to rx
kittens.on(.next(kitten)) // send result back to rx
//
// Another mess
//
@ -696,9 +699,9 @@ Every time you do this, somebody will probably write this code somewhere
```swift
kittens
.subscribeNext { kitten in
.subscribe(onNext: { kitten in
// so something with kitten
}
})
.addDisposableTo(disposeBag)
```
@ -714,7 +717,7 @@ If you are unsure how exactly some of the operators work, [playgrounds](../Rx.pl
## Error handling
The are two error mechanisms.
There are two error mechanisms.
### Asynchronous error handling mechanism in observables
@ -781,9 +784,9 @@ let subscription = myInterval(0.1)
.map { e in
return "This is simply \(e)"
}
.subscribeNext { n in
.subscribe(onNext: { n in
print(n)
}
})
NSThread.sleepForTimeInterval(0.5)
@ -795,15 +798,15 @@ will print
```
[my probe] subscribed
Subscribed
[my probe] -> Event Next(Box(0))
[my probe] -> Event next(Box(0))
This is simply 0
[my probe] -> Event Next(Box(1))
[my probe] -> Event next(Box(1))
This is simply 1
[my probe] -> Event Next(Box(2))
[my probe] -> Event next(Box(2))
This is simply 2
[my probe] -> Event Next(Box(3))
[my probe] -> Event next(Box(3))
This is simply 3
[my probe] -> Event Next(Box(4))
[my probe] -> Event next(Box(4))
This is simply 4
[my probe] dispose
Disposed
@ -819,17 +822,17 @@ extension ObservableType {
let subscription = self.subscribe { e in
print("event \(identifier) \(e)")
switch e {
case .Next(let value):
observer.on(.Next(value))
case .next(let value):
observer.on(.next(value))
case .Error(let error):
observer.on(.Error(error))
case .error(let error):
observer.on(.error(error))
case .Completed:
observer.on(.Completed)
case .completed:
observer.on(.completed)
}
}
return AnonymousDisposable {
return Disposables.create {
print("disposing \(identifier)")
subscription.dispose()
}
@ -849,9 +852,9 @@ In case you want to have some resource leak detection logic, the simplest method
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
*/
_ = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
.subscribeNext { _ in
print("Resource count \(RxSwift.resourceCount)")
}
.subscribe(onNext: { _ in
print("Resource count \(RxSwift.resourceCount)")
})
```
Most efficient way to test for memory leaks is:
@ -873,7 +876,7 @@ The reason why 2 navigations are suggested is because first navigation forces lo
Variable wraps a [`Subject`](http://reactivex.io/documentation/subject.html). More specifically it is a `BehaviorSubject`. Unlike `BehaviorSubject`, it only exposes `value` interface, so variable can never terminate or fail.
It will also broadcast it's current value immediately on subscription.
It will also broadcast its current value immediately on subscription.
After variable is deallocated, it will complete the observable sequence returned from `.asObservable()`.
@ -931,14 +934,14 @@ There are two built in ways this library supports KVO.
```swift
// KVO
extension NSObject {
public func rx_observe<E>(type: E.Type, _ keyPath: String, options: NSKeyValueObservingOptions, retainSelf: Bool = true) -> Observable<E?> {}
extension Reactive where Base: NSObject {
public func observe<E>(type: E.Type, _ keyPath: String, options: NSKeyValueObservingOptions, retainSelf: Bool = true) -> Observable<E?> {}
}
#if !DISABLE_SWIZZLING
// KVO
extension NSObject {
public func rx_observeWeakly<E>(type: E.Type, _ keyPath: String, options: NSKeyValueObservingOptions) -> Observable<E?> {}
extension Reactive where Base: NSObject {
public func observeWeakly<E>(type: E.Type, _ keyPath: String, options: NSKeyValueObservingOptions) -> Observable<E?> {}
}
#endif
```
@ -949,25 +952,25 @@ Example how to observe frame of `UIView`.
```swift
view
.rx_observe(CGRect.self, "frame")
.subscribeNext { frame in
.rx.observe(CGRect.self, "frame")
.subscribe(onNext: { frame in
...
}
})
```
or
```swift
view
.rx_observeWeakly(CGRect.self, "frame")
.subscribeNext { frame in
.rx.observeWeakly(CGRect.self, "frame")
.subscribe(onNext: { frame in
...
}
})
```
### `rx_observe`
### `rx.observe`
`rx_observe` is more performant because it's just a simple wrapper around KVO mechanism, but it has more limited usage scenarios
`rx.observe` is more performant because it's just a simple wrapper around KVO mechanism, but it has more limited usage scenarios
* it can be used to observe paths starting from `self` or from ancestors in ownership graph (`retainSelf = false`)
* it can be used to observe paths starting from descendants in ownership graph (`retainSelf = true`)
@ -976,14 +979,14 @@ view
E.g.
```swift
self.rx_observe(CGRect.self, "view.frame", retainSelf: false)
self.rx.observe(CGRect.self, "view.frame", retainSelf: false)
```
### `rx_observeWeakly`
### `rx.observeWeakly`
`rx_observeWeakly` has somewhat slower than `rx_observe` because it has to handle object deallocation in case of weak references.
`rx.observeWeakly` has somewhat slower than `rx.observe` because it has to handle object deallocation in case of weak references.
It can be used in all cases where `rx_observe` can be used and additionally
It can be used in all cases where `rx.observe` can be used and additionally
* because it won't retain observed target, it can be used to observe arbitrary object graph whose ownership relation is unknown
* it can be used to observe `weak` properties
@ -991,7 +994,7 @@ It can be used in all cases where `rx_observe` can be used and additionally
E.g.
```swift
someSuspiciousViewController.rx_observeWeakly(Bool.self, "behavingOk")
someSuspiciousViewController.rx.observeWeakly(Bool.self, "behavingOk")
```
### Observing structs
@ -1002,7 +1005,7 @@ KVO is an Objective-C mechanism so it relies heavily on `NSValue`.
When observing some other structures it is necessary to extract those structures from `NSValue` manually.
[Here](../RxCocoa/Common/KVORepresentable+CoreGraphics.swift) are examples how to extend KVO observing mechanism and `rx_observe*` methods for other structs by implementing `KVORepresentable` protocol.
[Here](../RxCocoa/Common/KVORepresentable+CoreGraphics.swift) are examples how to extend KVO observing mechanism and `rx.observe*` methods for other structs by implementing `KVORepresentable` protocol.
## UI layer tips
@ -1068,18 +1071,18 @@ let request = NSURLRequest(URL: NSURL(string: "http://en.wikipedia.org/w/api.php
If you want to just execute that request outside of composition with other observables, this is what needs to be done.
```swift
let responseJSON = NSURLSession.sharedSession().rx_JSON(request)
let responseJSON = NSURLSession.sharedSession().rx.JSON(request)
// no requests will be performed up to this point
// `responseJSON` is just a description how to fetch the response
let cancelRequest = responseJSON
// this will fire the request
.subscribeNext { json in
.subscribe(onNext: { json in
print(json)
}
})
NSThread.sleepForTimeInterval(3)
NSThread.sleep(forTimeInterval: 3.0)
// if you want to cancel request after 3 seconds have passed just call
cancelRequest.dispose()
@ -1091,7 +1094,7 @@ cancelRequest.dispose()
In case you want a more low level access to response, you can use:
```swift
NSURLSession.sharedSession().rx_response(myNSURLRequest)
NSURLSession.shared.rx.response(myNSURLRequest)
.debug("my request") // this will print out information to console
.flatMap { (data: NSData!, response: NSURLResponse!) -> Observable<String> in
if let response = response as? NSHTTPURLResponse {
@ -1099,12 +1102,12 @@ NSURLSession.sharedSession().rx_response(myNSURLRequest)
return just(transform(data))
}
else {
return failWith(yourNSError)
return Observable.error(yourNSError)
}
}
else {
rxFatalError("response = nil")
return failWith(yourNSError)
return Observable.error(yourNSError)
}
}
.subscribe { event in

View File

@ -1,47 +0,0 @@
**Please copy the following template [here](https://github.com/ReactiveX/RxSwift/issues/new) and fill in the missing fields so we can help you as soon as possible.**
**If you don't have something to report in the following format, maybe you don't really have an issue an it's easier and faster to resolve doubts in [slack channel](http://http://slack.rxswift.org/) first.**
```
*Short description*:
description here
*Code that reproduces the issue*:
code goes here
*Xcode version*:
Xcode version goes here
*Expected outcome*:
what do you expect to happen goes here
*What actually happens*:
what actually happens goes here
// filling additional information below is optional, but resolving your issue could be potentially a lot faster
*Integration method*:
(so we don't lose time investigating wrong integration)
* CocoaPods
* Carthage
* Git submodules
*I have multiple versions of Xcode installed*:
(so we can understand can this cause your issue)
* yes (which ones)
* no
*How long have I been using this project*:
(this is so we can understand your level of knowledge
and formulate the response in an appropriate manner)
* just starting
* I have a small code base
* I have a significant code base
```

View File

@ -16,10 +16,10 @@ let package = Package(
)
```
What does work:
What works:
* Distribution using Swift Package Manager
* Single Threaded mode (CurrentThreadScheduler)
* Half of unit tests are passing.
* Half of the unit tests are passing.
* Projects that can be compiled and "used":
* RxSwift
* RxBlocking
@ -28,4 +28,4 @@ What does work:
What doesn't work:
* Schedulers - because they are dependent on https://github.com/apple/swift-corelibs-libdispatch and it still hasn't been released
* Multithreading - still no access to c11 locks
* For some reason it looks like Swift compiler generates wrong code when using `ErrorType` on `Linux`, so don't use errors, otherwise you can get weird crashes.
* For some reason it looks like Swift compiler generates wrong code when using `Swift.Error` on `Linux`, so don't use errors, otherwise you can get weird crashes.

View File

@ -3,11 +3,11 @@ Math Behind Rx
## Duality between Observer and Iterator / Enumerator / Generator / Sequences
There is a duality between the observer and generator patterns. This is what enables us to transition from the async callback world to synchronous world of sequence transformations.
There is a duality between the observer and generator patterns. This is what enables us to transition from the async callback world to the synchronous world of sequence transformations.
In short, the enumerator and observer patterns both describe sequences. It's fairly obvious why the enumerator defines a sequence, but the observer is slightly more complicated.
In short, the enumerator and observer patterns both describe sequences. It's fairly obvious why the enumerator defines a sequence, but the observer is slightly more complicated.
There is, however, a pretty simple example that doesn't require a lot of mathematical knowledge. Assume that you are observing the position of your mouse cursor on screen at given time periods. Over time, these mouse positions form a sequence. This is, in essence, an observer sequence.
There is, however, a pretty simple example that doesn't require a lot of mathematical knowledge. Assume that you are observing the position of your mouse cursor on screen at given times. Over time, these mouse positions form a sequence. This is, in essence, an observable sequence.
There are two basic ways elements of a sequence can be accessed:

View File

@ -1,26 +1,26 @@
# Migration from RxSwift 1.9 to RxSwift 2.0 version
# Migration from RxSwift 1.9 to RxSwift 2.0
The migration should be pretty straightforward. The changes are mostly cosmetic, so all features are still there.
The migration should be pretty straightforward. Changes are mostly cosmetic, so all features are still there.
* Find replace all `>- ` to `.`
* Find replace all "variable" to "shareReplay(1)"
* Find replace all "catch" to "catchErrorJustReturn"
* Find replace all "returnElement" to "Observable.just"
* Find replace all "failWith" to "Observable.error"
* Find replace all "never" to "Observable.never"
* Find replace all "empty" to "Observable.empty"
* Since we've moved from `>-` to `.`, free functions are now methods, so it's `.switchLatest()`, `.distinctUntilChanged()`, ... instead of `>- switchLatest`, `>- distinctUntilChanged`
* we've moved from free functions to extensions so it's now `[a, b, c].concat()`, `.merge()`, ... instead of `concat([a, b, c])`, `merge(sequences)`
* Now it's `subscribe { n in ... }.addDisposableTo(disposeBag)` instead of `>- disposeBag.addDisposable`
* Method `next` on `Variable` is now `value` setter
* If you want to use `tableViews`/`collectionViews`, this is the basic use case now
* Find replace all `variable` to `shareReplay(1)`
* Find replace all `catch` to `catchErrorJustReturn`
* Find replace all `returnElement` to `Observable.just`
* Find replace all `failWith` to `Observable.error`
* Find replace all `never` to `Observable.never`
* Find replace all `empty` to `Observable.empty`
* Since we've moved from `>-` to `.`, free functions are now methods, so use `.switchLatest()`, `.distinctUntilChanged()`, ... instead of `>- switchLatest`, `>- distinctUntilChanged`
* We've moved from free functions to extensions so it's now `[a, b, c].concat()`, `.merge()`, ... instead of `concat([a, b, c])`, `merge(sequences)`
* Similarly, it's now `subscribe { n in ... }.addDisposableTo(disposeBag)` instead of `>- disposeBag.addDisposable`
* The method `next` on `Variable` is now `value` setter
* If you want to use `UITableView` and/or `UICollectionView`, this is the basic use case now:
```swift
viewModel.rows
.bindTo(resultsTableView.rx_itemsWithCellIdentifier("WikipediaSearchCell", cellType: WikipediaSearchCell.self)) { (_, viewModel, cell) in
cell.viewModel = viewModel
}
.addDisposableTo(disposeBag)
.bindTo(resultsTableView.rx_itemsWithCellIdentifier("WikipediaSearchCell", cellType: WikipediaSearchCell.self)) { (_, viewModel, cell) in
cell.viewModel = viewModel
}
.addDisposableTo(disposeBag)
```
If you have any more doubts how to write some concept in RxSwift 2.0 version, check out [Example app](../RxExample) or playgrounds.
If you have any doubts about how some concept in RxSwift 2.0 works, check out the [Example app](../RxExample) or playgrounds.

View File

@ -3,6 +3,6 @@
To use playgrounds:
* Open `Rx.xcworkspace`
* Build `RxSwift-OSX` scheme
* And then open `Rx` playground in `Rx.xcworkspace` tree view.
* Choose `View > Show Debug Area`
* Build the `RxSwift-OSX` scheme
* Open `Rx` playground in the `Rx.xcworkspace` tree view.
* Choose `View > Debug Area > Show Debug Area`

View File

@ -5,37 +5,37 @@ Schedulers
1. [Custom schedulers](#custom-schedulers)
1. [Builtin schedulers](#builtin-schedulers)
Schedulers abstract away mechanism for performing work.
Schedulers abstract away the mechanism for performing work.
Different mechanisms for performing work include, current thread, dispatch queues, operation queues, new threads, thread pools, run loops ...
Different mechanisms for performing work include the current thread, dispatch queues, operation queues, new threads, thread pools, and run loops.
There are two main operators that work with schedulers. `observeOn` and `subscribeOn`.
There are two main operators that work with schedulers, `observeOn` and `subscribeOn`.
If you want to perform work on different scheduler just use `observeOn(scheduler)` operator.
If you want to perform work on a different scheduler just use `observeOn(scheduler)` operator.
You would usually use `observeOn` a lot more often then `subscribeOn`.
You would usually use `observeOn` a lot more often than `subscribeOn`.
In case `observeOn` isn't explicitly specified, work will be performed on which ever thread/scheduler elements are generated.
In case `observeOn` isn't explicitly specified, work will be performed on whichever thread/scheduler elements are generated.
Example of using `observeOn` operator
Example of using the `observeOn` operator:
```
sequence1
.observeOn(backgroundScheduler)
.map { n in
print("This is performed on background scheduler")
print("This is performed on the background scheduler")
}
.observeOn(MainScheduler.instance)
.map { n in
print("This is performed on main scheduler")
print("This is performed on the main scheduler")
}
```
If you want to start sequence generation (`subscribe` method) and call dispose on a specific scheduler, use `subscribeOn(scheduler)`.
In case `subscribeOn` isn't explicitly specified, `subscribe` method will be called on the same thread/scheduler that `subscribeNext` or `subscribe` is called.
In case `subscribeOn` isn't explicitly specified, the `subscribe` method will be called on the same thread/scheduler on which `subscribe(onNext:)` or `subscribe` is called.
In case `subscribeOn` isn't explicitly specified, `dispose` method will be called on the same thread/scheduler that initiated disposing.
In case `subscribeOn` isn't explicitly specified, the `dispose` method will be called on the same thread/scheduler that initiated disposing.
In short, if no explicit scheduler is chosen, those methods will be called on current thread/scheduler.
@ -43,19 +43,19 @@ In short, if no explicit scheduler is chosen, those methods will be called on cu
Since schedulers can really be anything, and all operators that transform sequences need to preserve additional [implicit guarantees](GettingStarted.md#implicit-observable-guarantees), it is important what kind of schedulers are you creating.
In case scheduler is concurrent, Rx's `observeOn` and `subscribeOn` operators will make sure everything works perfect.
In case the scheduler is concurrent, Rx's `observeOn` and `subscribeOn` operators will make sure everything works perfectly.
If you use some scheduler that for which Rx can prove that it's serial, it will able to perform additional optimizations.
If you use some scheduler that Rx can prove is serial, it will be able to perform additional optimizations.
So far it only performing those optimizations for dispatch queue schedulers.
So far it only performs those optimizations for dispatch queue schedulers.
In case of serial dispatch queue schedulers `observeOn` is optimized to just a simple `dispatch_async` call.
In case of serial dispatch queue schedulers, `observeOn` is optimized to just a simple `dispatch_async` call.
# Custom schedulers
Besides current schedulers, you can write your own schedulers.
If you just want to describe who needs to perform work immediately, you can create your own scheduler by implementing `ImmediateScheduler` protocol.
If you just want to describe who needs to perform work immediately, you can create your own scheduler by implementing the `ImmediateScheduler` protocol.
```swift
public protocol ImmediateScheduler {
@ -63,7 +63,7 @@ public protocol ImmediateScheduler {
}
```
If you want to create new scheduler that supports time based operations, then you'll need to implement.
If you want to create a new scheduler that supports time based operations, then you'll need to implement the `Scheduler` protocol:
```swift
public protocol Scheduler: ImmediateScheduler {
@ -78,7 +78,7 @@ public protocol Scheduler: ImmediateScheduler {
}
```
In case scheduler only has periodic scheduling capabilities, you can inform Rx by implementing `PeriodicScheduler` protocol
In case the scheduler only has periodic scheduling capabilities, you can inform Rx by implementing the `PeriodicScheduler` protocol:
```swift
public protocol PeriodicScheduler : Scheduler {
@ -86,47 +86,47 @@ public protocol PeriodicScheduler : Scheduler {
}
```
In case scheduler doesn't support `PeriodicScheduling` capabilities, Rx will emulate periodic scheduling transparently.
In case the scheduler doesn't support `PeriodicScheduling` capabilities, Rx will emulate periodic scheduling transparently.
# Builtin schedulers
Rx can use all types of schedulers, but it can also perform some additional optimizations if it has proof that scheduler is serial.
These are currently supported schedulers
These are the currently supported schedulers:
## CurrentThreadScheduler (Serial scheduler)
Schedules units of work on the current thread.
This is the default scheduler for operators that generate elements.
This scheduler is also sometimes called `trampoline scheduler`.
This scheduler is also sometimes called a "trampoline scheduler".
If `CurrentThreadScheduler.instance.schedule(state) { }` is called for first time on some thread, scheduled action will be executed immediately and hidden queue will be created where all recursively scheduled actions will be temporarily enqueued.
If `CurrentThreadScheduler.instance.schedule(state) { }` is called for the first time on some thread, the scheduled action will be executed immediately and a hidden queue will be created where all recursively scheduled actions will be temporarily enqueued.
If some parent frame on call stack is already running `CurrentThreadScheduler.instance.schedule(state) { }`, scheduled action will be enqueued and executed when currently running action and all previously enqueued actions have finished executing.
If some parent frame on the call stack is already running `CurrentThreadScheduler.instance.schedule(state) { }`, the scheduled action will be enqueued and executed when the currently running action and all previously enqueued actions have finished executing.
## MainScheduler (Serial scheduler)
Abstracts work that needs to be performed on `MainThread`. In case `schedule` methods are called from main thread, it will perform action immediately without scheduling.
Abstracts work that needs to be performed on `MainThread`. In case `schedule` methods are called from main thread, it will perform the action immediately without scheduling.
This scheduler is usually used to perform UI work.
## SerialDispatchQueueScheduler (Serial scheduler)
Abstracts the work that needs to be performed on a specific `dispatch_queue_t`. It will make sure that even if concurrent dispatch queue is passed, it's transformed into a serial one.
Abstracts the work that needs to be performed on a specific `dispatch_queue_t`. It will make sure that even if a concurrent dispatch queue is passed, it's transformed into a serial one.
Serial schedulers enable certain optimizations for `observeOn`.
Main scheduler is an instance of `SerialDispatchQueueScheduler`.
The main scheduler is an instance of `SerialDispatchQueueScheduler`.
## ConcurrentDispatchQueueScheduler (Concurrent scheduler)
Abstracts the work that needs to be performed on a specific `dispatch_queue_t`. You can also pass a serial dispatch queue, it shouldn't cause any problems.
This scheduler is suitable when some work needs to be performed in background.
This scheduler is suitable when some work needs to be performed in the background.
## OperationQueueScheduler (Concurrent scheduler)
Abstracts the work that needs to be performed on a specific `NSOperationQueue`.
This scheduler is suitable for cases when there is some bigger chunk of work that needs to be performed in background and you want to fine tune concurrent processing using `maxConcurrentOperationCount`.
This scheduler is suitable for cases when there is some bigger chunk of work that needs to be performed in the background and you want to fine tune concurrent processing using `maxConcurrentOperationCount`.

View File

@ -23,7 +23,7 @@ extension ObservableType where E: MaybeCool {
* Always use operators to compose subscriptions.
**Avoid nesting subscribe calls at all cost. This is a bad smell.**
**Avoid nesting subscribe calls at all cost. This is a code smell.**
```swift
textField.rx_text.subscribeNext { text in

View File

@ -3,7 +3,7 @@ Unit Tests
## Testing custom operators
Library uses `RxTests` for all of RxSwift operator tests so you can take a look at AllTests-* target inside the project `Rx.xcworkspace`.
RxSwift uses `RxTests` for all operator tests, located in the AllTests-* target inside the project `Rx.xcworkspace`.
This is an example of a typical `RxSwift` operator unit test:
@ -12,16 +12,16 @@ func testMap_Range() {
// Initializes test scheduler.
// Test scheduler implements virtual time that is
// detached from local machine clock.
// That enables running the simulation as fast as possible
// This enables running the simulation as fast as possible
// and proving that all events have been handled.
let scheduler = TestScheduler(initialClock: 0)
// Creates a mock hot observable sequence.
// The sequence will emit events at following
// times no matter is there some observer subscribed.
// The sequence will emit events at desginated
// times, no matter if there are observers subscribed or not.
// (that's what hot means).
// This observable sequence will also record all subscriptions
// made during it's lifetime (`subscriptions` property).
// made during its lifetime (`subscriptions` property).
let xs = scheduler.createHotObservable([
next(150, 1), // first argument is virtual time, second argument is element value
next(210, 0),
@ -32,10 +32,10 @@ func testMap_Range() {
])
// `start` method will by default:
// * run the simulation and record all events
// * Run the simulation and record all events
// using observer referenced by `res`.
// * subscribe at virtual time 200
// * dispose subscription at virtual time 1000
// * Subscribe at virtual time 200
// * Dispose subscription at virtual time 1000
let res = scheduler.start { xs.map { $0 * 2 } }
let correctMessages = [
@ -57,9 +57,9 @@ func testMap_Range() {
## Testing operator compositions (view models, components)
Examples how to test operator compositions are contained inside `Rx.xcworkspace` > `RxExample-iOSTests` target.
Examples of how to test operator compositions are contained inside `Rx.xcworkspace` > `RxExample-iOSTests` target.
It easy to define `RxTests` extensions so you can write your tests in a readable way. Provided examples inside `RxExample-iOSTests` are just a tip how you can write those extensions, but there is a lot of possibilities how to write those tests.
It's easy to define `RxTests` extensions so you can write your tests in a readable way. Provided examples inside `RxExample-iOSTests` are just suggestions on how you can write those extensions, but there are a lot of possibilities on how to write those tests.
```swift
// expected events and test data

View File

@ -1,58 +1,58 @@
Units
=====
This document will try to describe what units are, why they are a useful concept, how to use and create them.
This document will try to describe what units are, why they are a useful concept, and how to use and create them.
* [Why](#why)
* [How do they work](#how-do-they-work)
* [Why are they named Units](#why-are-they-named-units)
* [How they work](#how-they-work)
* [Why they are named Units](#why-they-are-named-units)
* [RxCocoa units](#rxcocoa-units)
* [Driver unit](#driver-unit)
* [Why was it named Driver](#why-was-it-named-driver)
* [Why it's named Driver](#why-its-named-driver)
* [Practical usage example](#practical-usage-example)
## Why
Swift has a powerful type system that can be used to improve correctness and stability of applications and make using Rx a more intuitive and straightforward experience.
**Units are so far specific only to the [RxCocoa](https://github.com/ReactiveX/RxSwift/tree/master/RxCocoa) project, but the same principles could be implemented easily in other Rx implementations if necessary. There is no private API magic needed.**
**Units are specific only to the [RxCocoa](https://github.com/ReactiveX/RxSwift/tree/master/RxCocoa) project. However, the same principles could easily be implemented in other Rx implementations, if necessary. There is no private API magic needed.**
**Units are totally optional, you can use raw observable sequences everywhere in your program and all RxCocoa APIs work with observable sequences.**
**Units are totally optional. You can use raw observable sequences everywhere in your program and all RxCocoa APIs work with observable sequences.**
Units also help communicate and ensure observable sequence properties across interface boundaries.
Here are some of the properties that are important when writing Cocoa/UIKit applications.
* can't error out
* observe on main scheduler
* subscribe on main scheduler
* sharing side effects
* Can't error out
* Observe on main scheduler
* Subscribe on main scheduler
* Sharing side effects
## How do they work
## How they work
In its core it's just a struct with a reference to observable sequence.
At its core, it's just a struct with a reference to observable sequence.
You can think of them as a kind of builder pattern for observable sequences. When sequence is built, calling `.asObservable()` will transform a unit into a vanilla observable sequence.
You can think of them as a kind of builder pattern for observable sequences. When a sequence is built, calling `.asObservable()` will transform a unit into a vanilla observable sequence.
## Why are they named Units
## Why they are named Units
Analogies help reason about unfamiliar concepts, here are some ideas how units in physics and RxCocoa (rx units) are similar.
Using a couple analogies will help us reason about unfamiliar concepts. Here are some analogies showing how units in physics and RxCocoa (Rx units) are similar.
Analogies:
| Physical units | Rx units |
|-------------------------------------|---------------------------------------------------------------------|
| number (one value) | observable sequence (sequence of values) |
| dimensional unit (m, s, m/s, N ...) | Swift struct (Driver, ControlProperty, ControlEvent, Variable, ...) |
| dimensional unit (m, s, m/s, N ...) | Swift struct (Driver, ControlProperty, ControlEvent, ...) |
Physical unit is a pair of a number and a corresponding dimensional unit.<br/>
Rx unit is a pair of an observable sequence and a corresponding struct that describes observable sequence properties.
A physical unit is a pair of a number and a corresponding dimensional unit.<br/>
An Rx unit is a pair of an observable sequence and a corresponding struct that describes observable sequence properties.
Numbers are the basic composition glue when working with physical units: usually real or complex numbers.<br/>
Observable sequences are the basic composition glue when working with rx units.
Numbers are the basic compositional glue when working with physical units: usually real or complex numbers.<br/>
Observable sequences are the basic compositional glue when working with Rx units.
Physical units and [dimensional analysis](https://en.wikipedia.org/wiki/Dimensional_analysis#Checking_equations_that_involve_dimensions) can alleviate certain class of errors during complex calculations.<br/>
Type checking rx units can alleviate certain class of logic errors when writing reactive programs.
Physical units and [dimensional analysis](https://en.wikipedia.org/wiki/Dimensional_analysis#Checking_equations_that_involve_dimensions) can alleviate certain classes of errors during complex calculations.<br/>
Type checking Rx units can alleviate certain classes of logic errors when writing reactive programs.
Numbers have operators: `+`, `-`, `*`, `/`.<br/>
Observable sequences also have operators: `map`, `filter`, `flatMap` ...
@ -62,25 +62,25 @@ Physics units define operations by using corresponding number operations. E.g.
`/` operation on physical units is defined using `/` operation on numbers.
11 m / 0.5 s = ...
* first convert unit to **numbers** and **apply** `/` **operator** `11 / 0.5 = 22`
* then calculate unit (m / s)
* combine the result = 22 m / s
* First, convert the unit to **numbers** and **apply** `/` **operator** `11 / 0.5 = 22`
* Then, calculate the unit (m / s)
* Lastly, combine the result = 22 m / s
Rx units define operations by using corresponding observable sequence operations (this is how operators work internally). E.g.
The `map` operation on `Driver` is defined using the `map` operation on its observable sequence.
```swift
let d: Driver<Int> = Drive.just(11)
let d: Driver<Int> = Driver.just(11)
driver.map { $0 / 0.5 } = ...
```
* first convert driver to **observable sequence** and **apply** `map` **operator**
* First, convert `Driver` to **observable sequence** and **apply** `map` **operator**
```swift
let mapped = driver.asObservable().map { $0 / 0.5 } // this `map` is defined on observable sequence
```
* then combine that to get the unit value
* Then, combine that to get the unit value
```swift
let result = Driver(mapped)
```
@ -88,10 +88,10 @@ let result = Driver(mapped)
There is a set of basic units in physics [(`m`, `kg`, `s`, `A`, `K`, `cd`, `mol`)](https://en.wikipedia.org/wiki/SI_base_unit) that is orthogonal.<br/>
There is a set of basic interesting properties for observable sequences in `RxCocoa` that is orthogonal.
* can't error out
* observe on main scheduler
* subscribe on main scheduler
* sharing side effects
* Can't error out
* Observe on main scheduler
* Subscribe on main scheduler
* Sharing side effects
Derived units in physics sometimes have special names.<br/>
E.g.
@ -106,19 +106,18 @@ E.g.
```
Driver = (can't error out) * (observe on main scheduler) * (sharing side effects)
ControlProperty = (sharing side effects) * (subscribe on main scheduler)
Variable = (can't error out) * (sharing side effects)
```
Conversion between different units in physics is done with a help of operators defined on numbers `*`, `/`.<br/>
Conversion between different rx units in done with a help of observable sequence operators.
Conversion between different units in physics is done with the help of operators defined on numbers `*`, `/`.<br/>
Conversion between different Rx units in done with the help of observable sequence operators.
E.g.
```
can't error out = catchError
observe on main scheduler = observeOn(MainScheduler.instance)
subscribe on main scheduler = subscribeOn(MainScheduler.instance)
sharing side effects = share* (one of the `share` operators)
Can't error out = catchError
Observe on main scheduler = observeOn(MainScheduler.instance)
Subscribe on main scheduler = subscribeOn(MainScheduler.instance)
Sharing side effects = share* (one of the `share` operators)
```
@ -126,29 +125,24 @@ sharing side effects = share* (one of the `share` operators)
### Driver unit
* can't error out
* observe on main scheduler
* sharing side effects (`shareReplayLatestWhileConnected`)
* Can't error out
* Observe on main scheduler
* Sharing side effects (`shareReplayLatestWhileConnected`)
### ControlProperty / ControlEvent
* can't error out
* subscribe on main scheduler
* observe on main scheduler
* sharing side effects
### Variable
* can't error out
* sharing side effects
* Can't error out
* Subscribe on main scheduler
* Observe on main scheduler
* Sharing side effects
## Driver
This is the most elaborate unit. It's intention is to provide an intuitive way to write reactive code in UI layer.
This is the most elaborate unit. Its intention is to provide an intuitive way to write reactive code in the UI layer.
### Why was it named Driver
### Why it's named Driver
It's intended use case was to model sequences that drive your application.
Its intended use case was to model sequences that drive your application.
E.g.
* Drive UI from CoreData model
@ -156,9 +150,9 @@ E.g.
...
Like normal operating system drivers, in case one of those sequence errors out your application will stop responding to user input.
Like normal operating system drivers, in case a sequence errors out, your application will stop responding to user input.
It is also extremely important that those elements are observed on main thread because UI elements and application logic are usually not thread safe.
It is also extremely important that those elements are observed on the main thread because UI elements and application logic are usually not thread safe.
Also, `Driver` unit builds an observable sequence that shares side effects.
@ -167,10 +161,10 @@ E.g.
### Practical usage example
This is an typical beginner example.
This is a typical beginner example.
```swift
let results = query.rx_text
let results = query.rx.text
.throttle(0.3, scheduler: MainScheduler.instance)
.flatMapLatest { query in
fetchAutoCompleteItems(query)
@ -178,46 +172,46 @@ let results = query.rx_text
results
.map { "\($0.count)" }
.bindTo(resultCount.rx_text)
.bindTo(resultCount.rx.text)
.addDisposableTo(disposeBag)
results
.bindTo(resultsTableView.rx_itemsWithCellIdentifier("Cell")) { (_, result, cell) in
.bindTo(resultsTableView.rx.itemsWithCellIdentifier("Cell")) { (_, result, cell) in
cell.textLabel?.text = "\(result)"
}
.addDisposableTo(disposeBag)
```
The intended behavior of this code was to:
* throttle user input
* contact server and fetch a list of user results (once per query)
* then bind the results to two UI elements, results table view and a label that displays number of results
* Throttle user input
* Contact server and fetch a list of user results (once per query)
* Bind the results to two UI elements: results table view and a label that displays the number of results
So what are the problems with this code:
* in case the `fetchAutoCompleteItems` observable sequence errors out (connection failed, or parsing error), this error would unbind everything and UI wouldn't respond any more to new queries.
* in case `fetchAutoCompleteItems` returns results on some background thread, results would be bound to UI elements from a background thread and that could cause non deterministic crashes.
* results are bound to two UI elements, which means that for each user query two HTTP requests would be made, one for each UI element, which is not intended behavior.
So, what are the problems with this code?:
* If the `fetchAutoCompleteItems` observable sequence errors out (connection failed or parsing error), this error would unbind everything and the UI wouldn't respond any more to new queries.
* If `fetchAutoCompleteItems` returns results on some background thread, results would be bound to UI elements from a background thread which could cause non-deterministic crashes.
* Results are bound to two UI elements, which means that for each user query, two HTTP requests would be made, one for each UI element, which is not the intended behavior.
A more appropriate version of the code would look like this:
```swift
let results = query.rx_text
let results = query.rx.text
.throttle(0.3, scheduler: MainScheduler.instance)
.flatMapLatest { query in
fetchAutoCompleteItems(query)
.observeOn(MainScheduler.instance) // results are returned on MainScheduler
.catchErrorJustReturn([]) // in worst case, errors are handled
.observeOn(MainScheduler.instance) // results are returned on MainScheduler
.catchErrorJustReturn([]) // in the worst case, errors are handled
}
.shareReplay(1) // HTTP requests are shared and results replayed
// to all UI elements
.shareReplay(1) // HTTP requests are shared and results replayed
// to all UI elements
results
.map { "\($0.count)" }
.bindTo(resultCount.rx_text)
.bindTo(resultCount.rx.text)
.addDisposableTo(disposeBag)
results
.bindTo(resultTableView.rx_itemsWithCellIdentifier("Cell")) { (_, result, cell) in
.bindTo(resultTableView.rx.itemsWithCellIdentifier("Cell")) { (_, result, cell) in
cell.textLabel?.text = "\(result)"
}
.addDisposableTo(disposeBag)
@ -228,20 +222,20 @@ Making sure all of these requirements are properly handled in large systems can
The following code looks almost the same:
```swift
let results = query.rx_text.asDriver() // This converts normal sequence into `Driver` sequence.
let results = query.rx.text.asDriver() // This converts a normal sequence into a `Driver` sequence.
.throttle(0.3, scheduler: MainScheduler.instance)
.flatMapLatest { query in
fetchAutoCompleteItems(query)
.asDriver(onErrorJustReturn: []) // Builder just needs info what to return in case of error.
.asDriver(onErrorJustReturn: []) // Builder just needs info about what to return in case of error.
}
results
.map { "\($0.count)" }
.drive(resultCount.rx_text) // If there is `drive` method available instead of `bindTo`,
.addDisposableTo(disposeBag) // that means that compiler has proved all properties
.drive(resultCount.rx.text) // If there is a `drive` method available instead of `bindTo`,
.addDisposableTo(disposeBag) // that means that the compiler has proven that all properties
// are satisfied.
results
.drive(resultTableView.rx_itemsWithCellIdentifier("Cell")) { (_, result, cell) in
.drive(resultTableView.rx.itemsWithCellIdentifier("Cell")) { (_, result, cell) in
cell.textLabel?.text = "\(result)"
}
.addDisposableTo(disposeBag)
@ -249,37 +243,37 @@ results
So what is happening here?
This first `asDriver` method converts `ControlProperty` unit to `Driver` unit.
This first `asDriver` method converts the `ControlProperty` unit to a `Driver` unit.
```swift
query.rx_text.asDriver()
query.rx.text.asDriver()
```
Notice that there wasn't anything special that needed to be done. `Driver` has all of the properties of the `ControlProperty` unit plus some more. The underlying observable sequence is just wrapped as `Driver` unit, and that's it.
Notice that there wasn't anything special that needed to be done. `Driver` has all of the properties of the `ControlProperty` unit, plus some more. The underlying observable sequence is just wrapped as a `Driver` unit, and that's it.
The second change is
The second change is:
```swift
.asDriver(onErrorJustReturn: [])
.asDriver(onErrorJustReturn: [])
```
Any observable sequence can be converted to `Driver` unit, it just needs to satisfy 3 properties:
* can't error out
* observe on main scheduler
* sharing side effects (`shareReplayLatestWhileConnected`)
Any observable sequence can be converted to `Driver` unit, as long as it satisfies 3 properties:
* Can't error out
* Observe on main scheduler
* Sharing side effects (`shareReplayLatestWhileConnected`)
So how to make sure those properties are satisfied? Just use normal Rx operators. `asDriver(onErrorJustReturn: [])` is equivalent to following code.
So how do you make sure those properties are satisfied? Just use normal Rx operators. `asDriver(onErrorJustReturn: [])` is equivalent to following code.
```
let safeSequence = xs
.observeOn(MainScheduler.instance) // observe events on main scheduler
.observeOn(MainScheduler.instance) // observe events on main scheduler
.catchErrorJustReturn(onErrorJustReturn) // can't error out
.shareReplayLatestWhileConnected // side effects sharing
return Driver(raw: safeSequence) // wrap it up
```
The final piece is `drive` instead of using `bindTo`.
The final piece is using `drive` instead of using `bindTo`.
`drive` is defined only on `Driver` unit. It means that if you see `drive` somewhere in code, observable sequence that can never error out and observes elements on main thread is being bound to UI element. Which is exactly what is wanted.
`drive` is defined only on the `Driver` unit. This means that if you see `drive` somewhere in code, that observable sequence can never error out and it observes on the main thread, which is safe for binding to a UI element.
Theoretically, somebody could define `drive` method to work on `ObservableType` or some other interface, so creating a temporary definition with `let results: Driver<[Results]> = ...` before binding to UI elements would be necessary for complete proof, but we'll leave it up for reader to decide whether that is a realistic scenario.
Note however that, theoretically, someone could still define a `drive` method to work on `ObservableType` or some other interface, so to be extra safe, creating a temporary definition with `let results: Driver<[Results]> = ...` before binding to UI elements would be necessary for complete proof. However, we'll leave it up to the reader to decide whether this is a realistic scenario or not.

View File

@ -5,7 +5,7 @@ Warnings
The following is valid for the `subscribe*`, `bind*` and `drive*` family of functions that return `Disposable`.
Warning is probably presented in a context similar to this one:
You will receive a warning for doing something such as this:
```Swift
let xs: Observable<E> ....
@ -18,10 +18,10 @@ xs
...
}, onError: {
...
})
})
```
The `subscribe` function returns a subscription `Disposable` that can be used to cancel computation and free resources.
The `subscribe` function returns a subscription `Disposable` that can be used to cancel computation and free resources. However, not using it (and thus not disposing it) will result in an error.
The preferred way of terminating these fluent calls is by using a `DisposeBag`, either through chaining a call to `.addDisposableTo(disposeBag)` or by adding the disposable directly to the bag.
@ -41,11 +41,11 @@ xs
.addDisposableTo(disposeBag) // <--- note `addDisposableTo`
```
When `disposeBag` gets deallocated, the disposables contained in it will be automatically disposed.
When `disposeBag` gets deallocated, the disposables contained within it will be automatically disposed as well.
In the case where `xs` terminates in a predictable way with either a `Completed` or `Error` message, not handling the subscription `Disposable` won't leak any resources. However, even in this case, using a dispose bag is still the preferred way to handle subscription disposables. It ensures that element computation is always terminated at a predictable moment, and makes your code robust and future proof because resources will be properly disposed even if the implementation of `xs` changes.
Another way to make sure subscriptions and resources are tied with the lifetime of some object is by using the `takeUntil` operator.
Another way to make sure subscriptions and resources are tied to the lifetime of some object is by using the `takeUntil` operator.
```Swift
let xs: Observable<E> ....
@ -55,7 +55,7 @@ _ = xs
.filter { ... }
.map { ... }
.switchLatest()
.takeUntil(someObject.rx_deallocated) // <-- note the `takeUntil` operator
.takeUntil(someObject.deallocated) // <-- note the `takeUntil` operator
.subscribe(onNext: {
...
}, onError: {
@ -63,7 +63,7 @@ _ = xs
})
```
If ignoring the subscription `Disposable` is desired behavior, this is how to silence the compiler warning.
If ignoring the subscription `Disposable` is the desired behavior, this is how to silence the compiler warning.
```Swift
let xs: Observable<E> ....
@ -81,7 +81,7 @@ _ = xs // <-- note the underscore
### <a name="unused-observable"></a>Unused observable sequence (unused-observable)
Warning is probably presented in a context similar to this one:
You will receive a warning for doing something such as this:
```Swift
let xs: Observable<E> ....
@ -105,7 +105,7 @@ let ys = xs // <--- names definition as `ys`
.map { ... }
```
... or start computation based on that definition
... or start computation based on that definition
```Swift
let xs: Observable<E> ....
@ -114,9 +114,9 @@ let disposeBag = DisposeBag()
xs
.filter { ... }
.map { ... }
.subscribeNext { nextElement in // <-- note the `subscribe*` method
.subscribe(onNext: { nextElement in // <-- note the `subscribe*` method
// use the element
print(nextElement)
}
})
.addDisposableTo(disposeBag)
```

View File

@ -6,40 +6,40 @@
```swift
Observable.combineLatest(firstName.rx_text, lastName.rx_text) { $0 + " " + $1 }
.map { "Greeting \($0)" }
.bindTo(greetingLabel.rx_text)
.map { "Greetings, \($0)" }
.bindTo(greetingLabel.rx_text)
```
This also works with `UITableView`s and `UICollectionView`s.
```swift
viewModel
.rows
.bindTo(resultsTableView.rx_itemsWithCellIdentifier("WikipediaSearchCell", cellType: WikipediaSearchCell.self)) { (_, viewModel, cell) in
cell.title = viewModel.title
cell.url = viewModel.url
}
.addDisposableTo(disposeBag)
.rows
.bindTo(resultsTableView.rx_itemsWithCellIdentifier("WikipediaSearchCell", cellType: WikipediaSearchCell.self)) { (_, viewModel, cell) in
cell.title = viewModel.title
cell.url = viewModel.url
}
.addDisposableTo(disposeBag)
```
** Official suggestion is to always use `.addDisposableTo(disposeBag)` even though that's not necessary for simple bindings.**
**Official suggestion is to always use `.addDisposableTo(disposeBag)` even though that's not necessary for simple bindings.**
### Retries
It would be great if APIs wouldn't fail, but unfortunately they do. Let's say there is an API method
It would be great if APIs wouldn't fail, but unfortunately they do. Let's say there is an API method:
```swift
func doSomethingIncredible(forWho: String) throws -> IncredibleThing
```
If you are using this function as it is, it's really hard to do retries in case it fails. Not to mention complexities modeling [exponential backoffs](https://en.wikipedia.org/wiki/Exponential_backoff). Sure it's possible, but code would probably contain a lot of transient states that you really don't care about, and it won't be reusable.
If you are using this function as it is, it's really hard to do retries in case it fails. Not to mention complexities modeling [exponential backoffs](https://en.wikipedia.org/wiki/Exponential_backoff). Sure it's possible, but the code would probably contain a lot of transient states that you really don't care about, and it wouldn't be reusable.
You would ideally want to capture the essence of retrying, and to be able to apply it to any operation.
Ideally, you would want to capture the essence of retrying, and to be able to apply it to any operation.
This is how you can do simple retries with Rx
```swift
doSomethingIncredible("me")
doSomethingIncredible("me")
.retry(3)
```
@ -47,11 +47,11 @@ You can also easily create custom retry operators.
### Delegates
Instead of doing the tedious and non-expressive
Instead of doing the tedious and non-expressive:
```swift
public func scrollViewDidScroll(scrollView: UIScrollView) { // what scroll view is this bound to?
self.leftPositionConstraint.constant = scrollView.contentOffset.x
public func scrollViewDidScroll(scrollView: UIScrollView) { [weak self] // what scroll view is this bound to?
self?.leftPositionConstraint.constant = scrollView.contentOffset.x
}
```
@ -59,14 +59,14 @@ public func scrollViewDidScroll(scrollView: UIScrollView) { // what scroll view
```swift
self.resultsTableView
.rx_contentOffset
.map { $0.x }
.bindTo(self.leftPositionConstraint.rx_constant)
.rx_contentOffset
.map { $0.x }
.bindTo(self.leftPositionConstraint.rx_constant)
```
### KVO
Instead of
Instead of:
```
`TickTock` was deallocated while key value observers were still registered with it. Observation info was leaked, and may even become mistakenly attached to some other object.
@ -104,37 +104,38 @@ someSuspiciousViewController
### Notifications
Instead of using
Instead of using:
```swift
@available(iOS 4.0, *)
public func addObserverForName(name: String?, object obj: AnyObject?, queue: NSOperationQueue?, usingBlock block: (NSNotification) -> Void) -> NSObjectProtocol
@available(iOS 4.0, *)
public func addObserverForName(name: String?, object obj: AnyObject?, queue: NSOperationQueue?, usingBlock block: (NSNotification) -> Void) -> NSObjectProtocol
```
... just write
```swift
NSNotificationCenter.defaultCenter()
.rx_notification(UITextViewTextDidBeginEditingNotification, object: myTextView)
.map { /*do something with data*/ }
....
NSNotificationCenter.defaultCenter()
.rx_notification(UITextViewTextDidBeginEditingNotification, object: myTextView)
.map { /*do something with data*/ }
....
```
### Transient state
There is also a lot of problems with transient state when writing async programs. Typical example is autocomplete search box.
There are also a lot of problems with transient state when writing async programs. A typical example is an autocomplete search box.
If you were to write the autocomplete code without Rx, first problem that probably needs to be solved is when `c` in `abc` is typed, and there is a pending request for `ab`, pending request gets cancelled. Ok, that shouldn't be too hard to solve, you just create additional variable to hold reference to pending request.
If you were to write the autocomplete code without Rx, the first problem that probably needs to be solved is when `c` in `abc` is typed, and there is a pending request for `ab`, the pending request gets cancelled. OK, that shouldn't be too hard to solve, you just create an additional variable to hold reference to the pending request.
The next problem is if the request fails, you need to do that messy retry logic. But ok, a couple of more fields that capture number of retries that need to be cleaned up.
The next problem is if the request fails, you need to do that messy retry logic. But OK, a couple more fields that capture the number of retries that need to be cleaned up.
It would be great if program would wait for some time before firing that request to server, after all, we don't want to spam our servers in case somebody is in the process of fast typing something very long. Additional timer field maybe?
It would be great if the program would wait for some time before firing a request to the server. After all, we don't want to spam our servers in case somebody is in the process of typing something very long. An additional timer field maybe?
There is also a question of what needs to be shown on screen while that search is executing, and also what needs to be shown in case we fail even with all of the retries.
Writing all of this and properly testing it would be tedious. This is that same logic written with Rx.
```swift
searchTextField.rx_text
searchTextField.rx_text
.throttle(0.3, scheduler: MainScheduler.instance)
.distinctUntilChanged()
.flatMapLatest { query in
@ -148,22 +149,22 @@ Writing all of this and properly testing it would be tedious. This is that same
}
```
There is no additional flags or fields required. Rx takes care of all that transient mess.
There are no additional flags or fields required. Rx takes care of all that transient mess.
### Compositional disposal
Lets assume that there is a scenario where you want to display blurred images in a table view. The images should be first fetched from URL, then decoded and then blurred.
Let's assume that there is a scenario where you want to display blurred images in a table view. First, the images should be fetched from a URL, then decoded and then blurred.
It would also be nice if that entire process could be cancelled if a cell exits the visible table view area because bandwidth and processor time for blurring are expensive.
It would also be nice if that entire process could be cancelled if a cell exits the visible table view area since bandwidth and processor time for blurring are expensive.
It would also be nice if we didn't just immediately start to fetch image once the cell enters visible area because if user swipes really fast there could be a lot of requests fired and cancelled.
It would also be nice if we didn't just immediately start to fetch an image once the cell enters the visible area since, if user swipes really fast, there could be a lot of requests fired and cancelled.
It would be also nice if we could limit the number of concurrent image operations because blurring images is an expensive operation.
It would be also nice if we could limit the number of concurrent image operations because, again, blurring images is an expensive operation.
This is how we can do it using Rx.
This is how we can do it using Rx:
```swift
// this is conceptual solution
// this is a conceptual solution
let imageSubscription = imageURLs
.throttle(0.2, scheduler: MainScheduler.instance)
.flatMapLatest { imageURL in
@ -180,39 +181,39 @@ let imageSubscription = imageURLs
.addDisposableTo(reuseDisposeBag)
```
This code will do all that, and when `imageSubscription` is disposed it will cancel all dependent async operations and make sure no rogue image is bound to UI.
This code will do all that and, when `imageSubscription` is disposed, it will cancel all dependent async operations and make sure no rogue image is bound to the UI.
### Aggregating network requests
What if you need to fire two requests, and aggregate results when they have both finished?
What if you need to fire two requests and aggregate results when they have both finished?
Well, there is of course `zip` operator
Well, there is of course the `zip` operator
```swift
let userRequest: Observable<User> = API.getUser("me")
let friendsRequest: Observable<Friends> = API.getFriends("me")
let userRequest: Observable<User> = API.getUser("me")
let friendsRequest: Observable<Friends> = API.getFriends("me")
Observable.zip(userRequest, friendsRequest) { user, friends in
return (user, friends)
}
.subscribeNext { user, friends in
// bind them to user interface
}
Observable.zip(userRequest, friendsRequest) { user, friends in
return (user, friends)
}
.subscribeNext { user, friends in
// bind them to the user interface
}
```
So what if those APIs return results on a background thread, and binding has to happen on main UI thread? There is `observeOn`.
So what if those APIs return results on a background thread, and binding has to happen on the main UI thread? There is `observeOn`.
```swift
let userRequest: Observable<User> = API.getUser("me")
let friendsRequest: Observable<[Friend]> = API.getFriends("me")
let userRequest: Observable<User> = API.getUser("me")
let friendsRequest: Observable<[Friend]> = API.getFriends("me")
Observable.zip(userRequest, friendsRequest) { user, friends in
return (user, friends)
}
.observeOn(MainScheduler.instance)
.subscribeNext { user, friends in
// bind them to user interface
}
Observable.zip(userRequest, friendsRequest) { user, friends in
return (user, friends)
}
.observeOn(MainScheduler.instance)
.subscribeNext { user, friends in
// bind them to the user interface
}
```
There are many more practical use cases where Rx really shines.
@ -221,19 +222,19 @@ There are many more practical use cases where Rx really shines.
Languages that allow mutation make it easy to access global state and mutate it. Uncontrolled mutations of shared global state can easily cause [combinatorial explosion] (https://en.wikipedia.org/wiki/Combinatorial_explosion#Computing).
But on the other hand, when used in smart way, imperative languages can enable writing more efficient code closer to hardware.
But on the other hand, when used in a smart way, imperative languages can enable writing more efficient code closer to hardware.
The usual way to battle combinatorial explosion is to keep state as simple as possible, and use [unidirectional data flows](https://developer.apple.com/videos/play/wwdc2014-229) to model derived data.
This is what Rx really shines at.
This is where Rx really shines.
Rx is that sweet spot between functional and imperative world. It enables you to use immutable definitions and pure functions to process snapshots of mutable state in a reliable composable way.
Rx is that sweet spot between functional and imperative worlds. It enables you to use immutable definitions and pure functions to process snapshots of mutable state in a reliable composable way.
So what are some of the practical examples?
So what are some practical examples?
### Easy integration
And what if you need to create your own observable? It's pretty easy. This code is taken from RxCocoa and that's all you need to wrap HTTP requests with `NSURLSession`
What if you need to create your own observable? It's pretty easy. This code is taken from RxCocoa and that's all you need to wrap HTTP requests with `NSURLSession`
```swift
extension NSURLSession {
@ -266,30 +267,30 @@ extension NSURLSession {
### Benefits
In short using Rx will make your code:
In short, using Rx will make your code:
* composable <- because Rx is composition's nick name
* reusable <- because it's composable
* declarative <- because definitions are immutable and only data changes
* understandable and concise <- raising level of abstraction and removing transient states
* stable <- because Rx code is thoroughly unit tested
* less stateful <- because you are modeling application as unidirectional data flows
* without leaks <- because resource management is easy
* Composable <- Because Rx is composition's nickname
* Reusable <- Because it's composable
* Declarative <- Because definitions are immutable and only data changes
* Understandable and concise <- Raising the level of abstraction and removing transient states
* Stable <- Because Rx code is thoroughly unit tested
* Less stateful <- Because you are modeling applications as unidirectional data flows
* Without leaks <- Because resource management is easy
### It's not all or nothing
It is usually a good idea to model as much of your application as possible using Rx.
But what if you don't know all of the operators and does there even exist some operator that models your particular case?
But what if you don't know all of the operators and whether or not there even exists some operator that models your particular case?
Well, all of the Rx operators are based on math and should be intuitive.
The good news is that about 10-15 operators cover most typical use cases. And that list already includes some of the familiar ones like `map`, `filter`, `zip`, `observeOn` ...
The good news is that about 10-15 operators cover most typical use cases. And that list already includes some of the familiar ones like `map`, `filter`, `zip`, `observeOn`, ...
There is a huge list of [all Rx operators](http://reactivex.io/documentation/operators.html) and list of all of the [currently supported RxSwift operators](API.md).
For each operator there is [marble diagram](http://reactivex.io/documentation/operators/retry.html) that helps to explain how does it work.
For each operator, there is a [marble diagram](http://reactivex.io/documentation/operators/retry.html) that helps to explain how it works.
But what if you need some operator that isn't on that list? Well, you can make your own operator.
What if creating that kind of operator is really hard for some reason, or you have some legacy stateful piece of code that you need to work with? Well, you've got yourself in a mess, but you can [jump out of Rx monad](GettingStarted.md#life-happens) easily, process the data, and return back into it.
What if creating that kind of operator is really hard for some reason, or you have some legacy stateful piece of code that you need to work with? Well, you've got yourself in a mess, but you can [jump out of Rx monads](GettingStarted.md#life-happens) easily, process the data, and return back into it.

3
Gemfile Normal file
View File

@ -0,0 +1,3 @@
source 'https://rubygems.org'
gem 'danger'

34
Gemfile.lock Normal file
View File

@ -0,0 +1,34 @@
GEM
remote: https://rubygems.org/
specs:
addressable (2.3.8)
claide (1.0.0)
colored (1.2)
danger (0.7.4)
claide
colored (~> 1.2)
faraday
git
octokit (~> 4.2)
redcarpet (~> 3.3)
terminal-table (~> 1)
faraday (0.9.1)
multipart-post (>= 1.2, < 3)
git (1.3.0)
multipart-post (2.0.0)
octokit (4.3.0)
sawyer (~> 0.7.0, >= 0.5.3)
redcarpet (3.3.4)
sawyer (0.7.0)
addressable (>= 2.3.5, < 2.5)
faraday (~> 0.8, < 0.10)
terminal-table (1.4.5)
PLATFORMS
ruby
DEPENDENCIES
danger
BUNDLED WITH
1.12.5

51
ISSUE_TEMPLATE.md Normal file
View File

@ -0,0 +1,51 @@
:warning: If you don't have something to report in the following format, it will probably be easier and faster to ask in the [slack channel](http://http://slack.rxswift.org/) first. :warning:
**Short description of the issue**:
_description here_
**Self contained code example that reproduces the issue**:
```swift
code goes here
// If we can't get a self contained code example that reproduces the issue, there is a big chance we won't be able
// to help you because there is not much we can do.
// `Self contained code example` means:
// * that we should be able to just run the provided code without changing it.
// * that it will reproduce the issue upon running
```
**Xcode version**:
```
Xcode version goes here
```
**Expected outcome**:
_what you expect to happen goes here_
**What actually happens**:
_what actually happens goes here_
:warning: Fields below are optional for general issues or in case those questions aren't related to your issue, but filling them out will increase the chances of getting your issue resolved. :warning:
**Installation method**:
- [ ] CocoaPods
- [ ] Carthage
- [ ] Git submodules
**I have multiple versions of Xcode installed**:
(so we can know if this is a potential cause of your issue)
- [ ] yes (which ones)
- [ ] no
**Level of RxSwift knowledge**:
(this is so we can understand your level of knowledge
and formulate the response in an appropriate manner)
- [ ] just starting
- [ ] I have a small code base
- [ ] I have a significant code base

View File

@ -3,11 +3,6 @@ import PackageDescription
#if os(OSX)
let package = Package(
name: "RxSwift",
exclude: [
"Sources/RxCocoa",
"Sources/RxTests",
"Sources/AllTests"
],
targets: [
Target(
name: "RxSwift"
@ -32,14 +27,16 @@ let package = Package(
.Target(name: "RxTests")
]
)
],
exclude: [
"Sources/RxCocoa",
"Sources/RxTests",
"Sources/AllTests"
]
)
#elseif os(Linux)
let package = Package(
name: "RxSwift",
exclude: [
"Sources/RxCocoa",
],
targets: [
Target(
name: "RxSwift"
@ -64,6 +61,9 @@ let package = Package(
.Target(name: "RxTests")
]
)
],
exclude: [
"Sources/RxCocoa",
]
)
#endif

View File

@ -166,6 +166,7 @@
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
@ -201,6 +202,7 @@
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_VERSION = 3.0;
};
name = Release;
};

View File

@ -16,28 +16,29 @@ if Process.argc != 3 {
let sourceFilesRoot = Process.arguments[1]
let derivedData = Process.arguments[2]
let fileManager = NSFileManager()
let fileManager = FileManager()
func escape(value: String) -> String {
let escapedString = value.stringByReplacingOccurrencesOfString("\n", withString: "\\n")
let escapedString1 = escapedString.stringByReplacingOccurrencesOfString("\r", withString: "\\r")
let escapedString2 = escapedString1.stringByReplacingOccurrencesOfString("\"", withString: "\\\"")
let escapedString = value.replacingOccurrences(of: "\n", with: "\\n")
let escapedString1 = escapedString.replacingOccurrences(of: "\r", with: "\\r")
let escapedString2 = escapedString1.replacingOccurrences(of: "\"", with: "\\\"")
return "\"\(escapedString2)\""
}
func processFile(path: String, outputPath: String) -> String {
let rawContent = NSData(contentsOfFile: path)!
let content = NSString(data: rawContent, encoding: NSUTF8StringEncoding)! as String
let url = URL(fileURLWithPath: path)
let rawContent = try! Data(contentsOf: url)
let content = String(data: rawContent, encoding: String.Encoding.utf8)
let components = content.componentsSeparatedByString("<%")
guard let components = content?.components(separatedBy: "<%") else { return "" }
var functionContentComponents: [String] = []
functionContentComponents.append("var components: [String] = [\"// This file is autogenerated. Take a look at `Preprocessor` target in RxSwift project \\n\"]\n")
functionContentComponents.append("components.append(\(escape(components[0])))\n")
functionContentComponents.append("components.append(\(escape(value: components[0])))\n")
for codePlusSuffix in (components[1 ..< components.count]) {
let codePlusSuffixSeparated = codePlusSuffix.componentsSeparatedByString("%>")
let codePlusSuffixSeparated = codePlusSuffix.components(separatedBy: "%>")
if codePlusSuffixSeparated.count != 2 {
fatalError("Error in \(path) near \(codePlusSuffix)")
}
@ -46,24 +47,24 @@ func processFile(path: String, outputPath: String) -> String {
let suffix = codePlusSuffixSeparated[1]
if code.hasPrefix("=") {
functionContentComponents.append("components.append(String(\(code.substringFromIndex(code.startIndex.successor()))))\n")
functionContentComponents.append("components.append(String(\(code.substring(from: code.index(after: code.startIndex)))))\n")
}
else {
functionContentComponents.append("\(code)\n")
}
functionContentComponents.append("components.append(\(escape(suffix)));\n")
functionContentComponents.append("components.append(\(escape(value: suffix)));\n")
}
functionContentComponents.append("try! components.joinWithSeparator(\"\").writeToFile(\"\(outputPath)\", atomically: false, encoding: NSUTF8StringEncoding)")
functionContentComponents.append("try! components.joined(separator:\"\").write(toFile:\"\(outputPath)\", atomically: false, encoding: String.Encoding.utf8)")
return functionContentComponents.joinWithSeparator("")
return functionContentComponents.joined(separator: "")
}
func runCommand(path: String) {
_ = NSProcessInfo().processIdentifier
_ = ProcessInfo().processIdentifier
let task = NSTask()
let task = Task()
task.launchPath = "/bin/bash"
task.arguments = ["-c", "xcrun swift \"\(path)\""]
@ -71,34 +72,34 @@ func runCommand(path: String) {
task.waitUntilExit()
if task.terminationReason != NSTaskTerminationReason.Exit {
if task.terminationReason != Task.TerminationReason.exit {
exit(-1)
}
}
let files = fileManager.subpathsAtPath(sourceFilesRoot)
let files = try fileManager.subpathsOfDirectory(atPath: sourceFilesRoot)
var generateAllFiles = ["// Generated code\n", "import Foundation\n"]
for file in files! {
for file in files {
if ((file as NSString).pathExtension ?? "") != "tt" {
continue
}
print(file)
let path = (sourceFilesRoot as NSString).stringByAppendingPathComponent(file as String)
let path = (sourceFilesRoot as NSString).appendingPathComponent(file as String)
let endIndex = path.index(before: path.index(before: path.index(before: path.endIndex)))
let outputPath = path.substring(to: endIndex) + ".swift"
let outputPath = path.substringToIndex(path.endIndex.predecessor().predecessor().predecessor()) + ".swift"
generateAllFiles.append("_ = { () -> Void in\n\(processFile(path, outputPath: outputPath))\n}()\n")
generateAllFiles.append("_ = { () -> Void in\n\(processFile(path: path, outputPath: outputPath))\n}()\n")
}
let script = generateAllFiles.joinWithSeparator("")
let scriptPath = (derivedData as NSString).stringByAppendingPathComponent("_preprocessor.sh")
let script = generateAllFiles.joined(separator: "")
let scriptPath = (derivedData as NSString).appendingPathComponent("_preprocessor.sh")
do {
try script.writeToFile(scriptPath, atomically: true, encoding: NSUTF8StringEncoding)
try script.write(toFile: scriptPath, atomically: true, encoding: String.Encoding.utf8)
} catch _ {
}
runCommand(scriptPath)
runCommand(path: scriptPath)

140
README.md
View File

@ -3,11 +3,12 @@
[![Travis CI](https://travis-ci.org/ReactiveX/RxSwift.svg?branch=master)](https://travis-ci.org/ReactiveX/RxSwift) ![platforms](https://img.shields.io/badge/platforms-iOS%20%7C%20OSX%20%7C%20tvOS%20%7C%20watchOS%20%7C%20Linux%28experimental%29-333333.svg) ![pod](https://img.shields.io/cocoapods/v/RxSwift.svg) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
Xcode 7.3 Swift 2.2 required
## About Rx
**:warning: This readme describes RxSwift 3.0 version that requires Swift 3.0:warning:**
**:warning: If you are looking for Swift 2.3 compatible version, please take a look at RxSwift ~> 2.0 versions and [swift-2.3](https://github.com/ReactiveX/RxSwift/tree/rxswift-2.0) branch :warning:**
Rx is a [generic abstraction of computation](https://youtu.be/looJcaeboBY) expressed through `Observable<Element>` interface.
This is a Swift version of [Rx](https://github.com/Reactive-Extensions/Rx.NET).
@ -34,19 +35,20 @@ KVO observing, async operations and streams are all unified under [abstraction o
* [what are hot and cold observable sequences?](Documentation/HotAndColdObservables.md)
* [what does the the public API look like?](Documentation/API.md)
###### ... install
* Integrate RxSwift/RxCocoa with my app. [Installation Guide](Documentation/Installation.md)
###### ... hack around
* with example app. [Running Example App](Documentation/ExampleApp.md)
* with the example app. [Running Example App](Documentation/ExampleApp.md)
* with operators in playgrounds. [Playgrounds](Documentation/Playgrounds.md)
###### ... interact
* All of this is great, but it would be nice to talk with other people using RxSwift and exchange experiences. <br />[![Slack channel](http://slack.rxswift.org/badge.svg)](http://slack.rxswift.org) [Join Slack Channel](http://slack.rxswift.org/)
* Report a problem using the library. [Open an Issue With Bug Template](Documentation/IssueTemplate.md)
* All of this is great, but it would be nice to talk with other people using RxSwift and exchange experiences. <br />[![Slack channel](http://rxswift-slack.herokuapp.com/badge.svg)](http://slack.rxswift.org) [Join Slack Channel](http://rxswift-slack.herokuapp.com)
* Report a problem using the library. [Open an Issue With Bug Template](ISSUE_TEMPLATE.md)
* Request a new feature. [Open an Issue With Feature Request Template](Documentation/NewFeatureRequestTemplate.md)
@ -65,7 +67,131 @@ KVO observing, async operations and streams are all unified under [abstraction o
* Does this exist for Android? [RxJava](https://github.com/ReactiveX/RxJava)
* Where is all of this going, what is the future, what about reactive architectures, how do you design entire apps this way? [Cycle.js](https://github.com/cyclejs/cycle-core) - this is javascript, but [RxJS](https://github.com/Reactive-Extensions/RxJS) is javascript version of Rx.
##### References
## Usage
<table>
<tr>
<th width="30%">Here's an example</th>
<th width="30%">In Action</th>
</tr>
<tr>
<td>Define search for GitHub repositories ...</td>
<th rowspan="9"><img src="https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/GithubSearch.gif"></th>
</tr>
<tr>
<td><div class="highlight highlight-source-swift"><pre>
let searchResults = searchBar.rx.text
.throttle(0.3, scheduler: MainScheduler.instance)
.distinctUntilChanged()
.flatMapLatest { query -> Observable<[Repository]> in
if query.isEmpty {
return Observable.just([])
}
return searchGitHub(query)
.catchErrorJustReturn([])
}
.observeOn(MainScheduler.instance)</pre></div></td>
</tr>
<tr>
<td>... then bind the results to your tableview</td>
</tr>
<tr>
<td width="30%"><div class="highlight highlight-source-swift"><pre>
searchResults
.bindTo(tableView.rx.items(cellIdentifier: "Cell")) {
(index, repository: Repository, cell) in
cell.textLabel?.text = repository.name
cell.detailTextLabel?.text = repository.url
}
.addDisposableTo(disposeBag)</pre></div></td>
</tr>
</table>
## Requirements
* Xcode 8.0 beta 6 (8S201h)
* Swift 3.0
* iOS 8.0+
* Mac OS X 10.10+
* tvOS 9.0+
* watchOS 2.0+
## Installation
Rx doesn't contain any external dependencies.
These are currently the supported options:
### Manual
Open Rx.xcworkspace, choose `RxExample` and hit run. This method will build everything and run the sample app
### [CocoaPods](https://guides.cocoapods.org/using/using-cocoapods.html)
```
# Podfile
use_frameworks!
target 'YOUR_TARGET_NAME' do
pod 'RxSwift', '~> 3.0.0.alpha.1'
pod 'RxCocoa', '~> 3.0.0.alpha.1'
end
# RxTests and RxBlocking make the most sense in the context of unit/integration tests
target 'YOUR_TESTING_TARGET' do
pod 'RxBlocking', '~> 3.0.0.alpha.1'
pod 'RxTests', '~> 3.0.0.alpha.1'
end
```
Replace `YOUR_TARGET_NAME` and then, in the `Podfile` directory, type:
**:warning: If you want to use CocoaPods with Xcode 8.0 beta and Swift 3.0, you might need to add the following
lines to your podfile: :warning:**
```
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['SWIFT_VERSION'] = '3.0'
config.build_settings['MACOSX_DEPLOYMENT_TARGET'] = '10.10'
end
end
end
```
```
$ pod install
```
### [Carthage](https://github.com/Carthage/Carthage)
Add this to `Cartfile`
```
github "ReactiveX/RxSwift" "3.0.0.alpha.1"
```
```
$ carthage update
```
### Manually using git submodules
* Add RxSwift as a submodule
```
$ git submodule add git@github.com:ReactiveX/RxSwift.git
```
* Drag `Rx.xcodeproj` into Project Navigator
* Go to `Project > Targets > Build Phases > Link Binary With Libraries`, click `+` and select `RxSwift-[Platform]` and `RxCocoa-[Platform]` targets
## References
* [http://reactivex.io/](http://reactivex.io/)
* [Reactive Extensions GitHub (GitHub)](https://github.com/Reactive-Extensions)

View File

@ -1,290 +0,0 @@
/*:
> # IMPORTANT: To use `Rx.playground`, please:
1. Open `Rx.xcworkspace`
2. Build `RxSwift-OSX` scheme
3. And then open `Rx` playground in `Rx.xcworkspace` tree view.
4. Choose `View > Show Debug Area`
*/
//: [<< Previous](@previous) - [Index](Index)
import RxSwift
/*:
## Combination operators
Operators that work with multiple source Observables to create a single Observable.
*/
/*:
### `startWith`
emit a specified sequence of items before beginning to emit the items from the source Observable
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/startwith.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/startwith.html )
*/
example("startWith") {
let subscription = Observable.of(4, 5, 6, 7, 8, 9)
.startWith(3)
.startWith(2)
.startWith(1)
.startWith(0)
.subscribe {
print($0)
}
}
/*:
### `combineLatest`
when an item is emitted by either of two Observables, combine the latest item emitted by each Observable via a specified function and emit items based on the results of this function
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/combinelatest.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/combinelatest.html )
*/
example("combineLatest 1") {
let intOb1 = PublishSubject<String>()
let intOb2 = PublishSubject<Int>()
_ = Observable.combineLatest(intOb1, intOb2) {
"\($0) \($1)"
}
.subscribe {
print($0)
}
intOb1.on(.Next("A"))
intOb2.on(.Next(1))
intOb1.on(.Next("B"))
intOb2.on(.Next(2))
}
//: To produce output, at least one element has to be received from each sequence in arguements.
example("combineLatest 2") {
let intOb1 = Observable.just(2)
let intOb2 = Observable.of(0, 1, 2, 3, 4)
_ = Observable.combineLatest(intOb1, intOb2) {
$0 * $1
}
.subscribe {
print($0)
}
}
//: Combine latest has versions with more than 2 arguments.
example("combineLatest 3") {
let intOb1 = Observable.just(2)
let intOb2 = Observable.of(0, 1, 2, 3)
let intOb3 = Observable.of(0, 1, 2, 3, 4)
_ = Observable.combineLatest(intOb1, intOb2, intOb3) {
($0 + $1) * $2
}
.subscribe {
print($0)
}
}
//: Combinelatest version that allows combining sequences with different types.
example("combineLatest 4") {
let intOb = Observable.just(2)
let stringOb = Observable.just("a")
_ = Observable.combineLatest(intOb, stringOb) {
"\($0) " + $1
}
.subscribe {
print($0)
}
}
//: `combineLatest` extension method for Array of `ObservableType` conformable types
//: The array must be formed by `Observables` of the same type.
example("combineLatest 5") {
let intOb1 = Observable.just(2)
let intOb2 = Observable.of(0, 1, 2, 3)
let intOb3 = Observable.of(0, 1, 2, 3, 4)
_ = [intOb1, intOb2, intOb3].combineLatest { intArray -> Int in
Int((intArray[0] + intArray[1]) * intArray[2])
}
.subscribe { (event: Event<Int>) -> Void in
print(event)
}
}
/*:
### `zip`
combine the emissions of multiple Observables together via a specified function and emit single items for each combination based on the results of this function
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/zip.png)
[More info in reactive.io website](http://reactivex.io/documentation/operators/zip.html)
*/
example("zip 1") {
let intOb1 = PublishSubject<String>()
let intOb2 = PublishSubject<Int>()
_ = Observable.zip(intOb1, intOb2) {
"\($0) \($1)"
}
.subscribe {
print($0)
}
intOb1.on(.Next("A"))
intOb2.on(.Next(1))
intOb1.on(.Next("B"))
intOb1.on(.Next("C"))
intOb2.on(.Next(2))
}
example("zip 2") {
let intOb1 = Observable.just(2)
let intOb2 = Observable.of(0, 1, 2, 3, 4)
_ = Observable.zip(intOb1, intOb2) {
$0 * $1
}
.subscribe {
print($0)
}
}
example("zip 3") {
let intOb1 = Observable.of(0, 1)
let intOb2 = Observable.of(0, 1, 2, 3)
let intOb3 = Observable.of(0, 1, 2, 3, 4)
_ = Observable.zip(intOb1, intOb2, intOb3) {
($0 + $1) * $2
}
.subscribe {
print($0)
}
}
/*:
### `merge`
combine multiple Observables into one by merging their emissions
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/merge.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/merge.html )
*/
example("merge 1") {
let subject1 = PublishSubject<Int>()
let subject2 = PublishSubject<Int>()
_ = Observable.of(subject1, subject2)
.merge()
.subscribeNext { int in
print(int)
}
subject1.on(.Next(20))
subject1.on(.Next(40))
subject1.on(.Next(60))
subject2.on(.Next(1))
subject1.on(.Next(80))
subject1.on(.Next(100))
subject2.on(.Next(1))
}
example("merge 2") {
let subject1 = PublishSubject<Int>()
let subject2 = PublishSubject<Int>()
_ = Observable.of(subject1, subject2)
.merge(maxConcurrent: 2)
.subscribe {
print($0)
}
subject1.on(.Next(20))
subject1.on(.Next(40))
subject1.on(.Next(60))
subject2.on(.Next(1))
subject1.on(.Next(80))
subject1.on(.Next(100))
subject2.on(.Next(1))
}
/*:
### `switchLatest`
convert an Observable that emits Observables into a single Observable that emits the items emitted by the most-recently-emitted of those Observables
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/switch.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/switch.html )
*/
example("switchLatest") {
let var1 = Variable(0)
let var2 = Variable(200)
// var3 is like an Observable<Observable<Int>>
let var3 = Variable(var1.asObservable())
let d = var3
.asObservable()
.switchLatest()
.subscribe {
print($0)
}
var1.value = 1
var1.value = 2
var1.value = 3
var1.value = 4
var3.value = var2.asObservable()
var2.value = 201
var1.value = 5
var1.value = 6
var1.value = 7
}
//: [Index](Index) - [Next >>](@next)

View File

@ -0,0 +1,160 @@
/*:
> # IMPORTANT: To use **Rx.playground**:
1. Open **Rx.xcworkspace**.
1. Build the **RxSwift-OSX** scheme (**Product** **Build**).
1. Open **Rx** playground in the **Project navigator**.
1. Show the Debug Area (**View** **Debug Area** **Show Debug Area**).
----
[Previous](@previous) - [Table of Contents](Table_of_Contents)
*/
import RxSwift
/*:
# Combination Operators
Operators that combine multiple source `Observable`s into a single `Observable`.
## `startWith`
Emits the specified sequence of elements before beginning to emit the elements from the source `Observable`. [More info](http://reactivex.io/documentation/operators/startwith.html)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/startwith.png)
*/
example("startWith") {
let disposeBag = DisposeBag()
Observable.of("🐶", "🐱", "🐭", "🐹")
.startWith("1")
.startWith("2")
.startWith("3", "🅰️", "🅱️")
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}
/*:
> As this example demonstrates, `startWith` can be chained on a last-in-first-out basis, i.e., each successive `startWith`'s elements will be prepended before the prior `startWith`'s elements.
----
## `merge`
Combines elements from source `Observable` sequences into a single new `Observable` sequence, and will emit each element as it is emitted by each source `Observable` sequence. [More info](http://reactivex.io/documentation/operators/merge.html)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/merge.png)
*/
example("merge") {
let disposeBag = DisposeBag()
let subject1 = PublishSubject<String>()
let subject2 = PublishSubject<String>()
Observable.of(subject1, subject2)
.merge()
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
subject1.onNext("🅰️")
subject1.onNext("🅱️")
subject2.onNext("")
subject2.onNext("")
subject1.onNext("🆎")
subject2.onNext("")
}
/*:
----
## `zip`
Combines up to 8 source `Observable` sequences into a single new `Observable` sequence, and will emit from the combined `Observable` sequence the elements from each of the source `Observable` sequences at the corresponding index. [More info](http://reactivex.io/documentation/operators/zip.html)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/zip.png)
*/
example("zip") {
let disposeBag = DisposeBag()
let stringSubject = PublishSubject<String>()
let intSubject = PublishSubject<Int>()
Observable.zip(stringSubject, intSubject) { stringElement, intElement in
"\(stringElement) \(intElement)"
}
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
stringSubject.onNext("🅰️")
stringSubject.onNext("🅱️")
intSubject.onNext(1)
intSubject.onNext(2)
stringSubject.onNext("🆎")
intSubject.onNext(3)
}
/*:
----
## `combineLatest`
Combines up to 8 source `Observable` sequences into a single new `Observable` sequence, and will begin emitting from the combined `Observable` sequence the latest elements of each source `Observable` sequence once all source sequences have emitted at least one element, and also when any of the source `Observable` sequences emits a new element. [More info](http://reactivex.io/documentation/operators/combinelatest.html)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/combinelatest.png)
*/
example("combineLatest") {
let disposeBag = DisposeBag()
let stringSubject = PublishSubject<String>()
let intSubject = PublishSubject<Int>()
Observable.combineLatest(stringSubject, intSubject) { stringElement, intElement in
"\(stringElement) \(intElement)"
}
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
stringSubject.onNext("🅰️")
stringSubject.onNext("🅱️")
intSubject.onNext(1)
intSubject.onNext(2)
stringSubject.onNext("🆎")
}
//: There is also a `combineLatest` extension on `Array`:
example("Array.combineLatest") {
let disposeBag = DisposeBag()
let stringObservable = Observable.just("❤️")
let fruitObservable = Observable.from(["🍎", "🍐", "🍊"])
let animalObservable = Observable.of("🐶", "🐱", "🐭", "🐹")
[stringObservable, fruitObservable, animalObservable].combineLatest {
"\($0[0]) \($0[1]) \($0[2])"
}
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}
/*:
> The `combineLatest` extension on `Array` requires that all source `Observable` sequences are of the same type.
----
## `switchLatest`
Transforms the elements emitted by an `Observable` sequence into `Observable` sequences, and emits elements from the most recent inner `Observable` sequence. [More info](http://reactivex.io/documentation/operators/switch.html)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/switch.png)
*/
example("switchLatest") {
let disposeBag = DisposeBag()
let subject1 = BehaviorSubject(value: "⚽️")
let subject2 = BehaviorSubject(value: "🍎")
let variable = Variable(subject1)
variable.asObservable()
.switchLatest()
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
subject1.onNext("🏈")
subject1.onNext("🏀")
variable.value = subject2
subject1.onNext("⚾️")
subject2.onNext("🍐")
}
/*:
> In this example, adding onto `subject1` after setting `variable.value` to `subject2` has no effect, because only the most recent inner `Observable` sequence (`subject2`) will emit elements.
*/
//: [Next](@next) - [Table of Contents](Table_of_Contents)

View File

@ -1,82 +0,0 @@
/*:
> # IMPORTANT: To use `Rx.playground`, please:
1. Open `Rx.xcworkspace`
2. Build `RxSwift-OSX` scheme
3. And then open `Rx` playground in `Rx.xcworkspace` tree view.
4. Choose `View > Show Debug Area`
*/
//: [<< Previous](@previous) - [Index](Index)
import Cocoa
import RxSwift
/*:
## Conditional and Boolean Operators
Operators that evaluate one or more Observables or items emitted by Observables.
*/
/*:
### `takeUntil`
Discard any items emitted by an Observable after a second Observable emits an item or terminates.
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/takeuntil.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/takeuntil.html )
*/
example("takeUntil") {
let originalSequence = PublishSubject<Int>()
let whenThisSendsNextWorldStops = PublishSubject<Int>()
_ = originalSequence
.takeUntil(whenThisSendsNextWorldStops)
.subscribe {
print($0)
}
originalSequence.on(.Next(1))
originalSequence.on(.Next(2))
originalSequence.on(.Next(3))
originalSequence.on(.Next(4))
whenThisSendsNextWorldStops.on(.Next(1))
originalSequence.on(.Next(5))
}
/*:
### `takeWhile`
Mirror items emitted by an Observable until a specified condition becomes false
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/takewhile.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/takewhile.html )
*/
example("takeWhile") {
let sequence = PublishSubject<Int>()
_ = sequence
.takeWhile { int in
int < 4
}
.subscribe {
print($0)
}
sequence.on(.Next(1))
sequence.on(.Next(2))
sequence.on(.Next(3))
sequence.on(.Next(4))
sequence.on(.Next(5))
}
//: [Index](Index) - [Next >>](@next)

View File

@ -1,221 +0,0 @@
/*:
> # IMPORTANT: To use `Rx.playground`, please:
1. Open `Rx.xcworkspace`
2. Build `RxSwift-OSX` scheme
3. And then open `Rx` playground in `Rx.xcworkspace` tree view.
4. Choose `View > Show Debug Area`
*/
//: [<< Previous](@previous) - [Index](Index)
import RxSwift
/*:
## Below every example there is a commented method call that runs that example. To run the example just uncomment that part.
E.g. `//sampleWithoutConnectableOperators()`
*/
/*:
## Connectable Observable Operators
A Connectable Observable resembles an ordinary Observable, except that it does not begin emitting items when it is subscribed to, but only when its connect() method is called. In this way you can wait for all intended Subscribers to subscribe to the Observable before the Observable begins emitting items.
Specialty Observables that have more precisely-controlled subscription dynamics.
*/
func sampleWithoutConnectableOperators() {
let int1 = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
_ = int1
.subscribe {
print("first subscription \($0)")
}
delay(5) {
_ = int1
.subscribe {
print("second subscription \($0)")
}
}
}
//sampleWithoutConnectableOperators()
/*:
### `multicast`
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/publishconnect.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/publish.html )
*/
func sampleWithMulticast() {
let subject1 = PublishSubject<Int64>()
_ = subject1
.subscribe {
print("Subject \($0)")
}
let int1 = Observable<Int64>.interval(1, scheduler: MainScheduler.instance)
.multicast(subject1)
_ = int1
.subscribe {
print("first subscription \($0)")
}
delay(2) {
int1.connect()
}
delay(4) {
_ = int1
.subscribe {
print("second subscription \($0)")
}
}
delay(6) {
_ = int1
.subscribe {
print("third subscription \($0)")
}
}
}
// sampleWithMulticast()
/*:
### `replay`
Ensure that all observers see the same sequence of emitted items, even if they subscribe after the Observable has begun emitting items.
publish = multicast + replay subject
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/replay.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/replay.html )
*/
func sampleWithReplayBuffer0() {
let int1 = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
.replay(0)
_ = int1
.subscribe {
print("first subscription \($0)")
}
delay(2) {
int1.connect()
}
delay(4) {
_ = int1
.subscribe {
print("second subscription \($0)")
}
}
delay(6) {
_ = int1
.subscribe {
print("third subscription \($0)")
}
}
}
// sampleWithReplayBuffer0()
func sampleWithReplayBuffer2() {
print("--- sampleWithReplayBuffer2 ---\n")
let int1 = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
.replay(2)
_ = int1
.subscribe {
print("first subscription \($0)")
}
delay(2) {
int1.connect()
}
delay(4) {
_ = int1
.subscribe {
print("second subscription \($0)")
}
}
delay(6) {
_ = int1
.subscribe {
print("third subscription \($0)")
}
}
}
// sampleWithReplayBuffer2()
/*:
### `publish`
Convert an ordinary Observable into a connectable Observable.
publish = multicast + publish subject
so publish is basically replay(0)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/publish.html )
*/
func sampleWithPublish() {
let int1 = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
.publish()
_ = int1
.subscribe {
print("first subscription \($0)")
}
delay(2) {
int1.connect()
}
delay(4) {
_ = int1
.subscribe {
print("second subscription \($0)")
}
}
delay(6) {
_ = int1
.subscribe {
print("third subscription \($0)")
}
}
}
// sampleWithPublish()
playgroundShouldContinueIndefinitely()
//: [Index](Index)

View File

@ -0,0 +1,133 @@
/*:
> # IMPORTANT: To use **Rx.playground**:
1. Open **Rx.xcworkspace**.
1. Build the **RxSwift-OSX** scheme (**Product** **Build**).
1. Open **Rx** playground in the **Project navigator**.
1. Show the Debug Area (**View** **Debug Area** **Show Debug Area**).
----
[Previous](@previous) - [Table of Contents](Table_of_Contents)
*/
import RxSwift
playgroundShouldContinueIndefinitely()
/*:
## Connectable Operators
Connectable `Observable` sequences resembles ordinary `Observable` sequences, except that they not begin emitting elements when subscribed to, but instead, only when their `connect()` method is called. In this way, you can wait for all intended subscribers to subscribe to a connectable `Observable` sequence before it begins emitting elements.
> Within each example on this page is a commented-out method. Uncomment that method to run the example, and then comment it out again to stop running the example.
#
Before learning about connectable operators, let's take a look at an example of a non-connectable operator:
*/
func sampleWithoutConnectableOperators() {
printExampleHeader(#function)
let interval = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
_ = interval
.subscribe(onNext: { print("Subscription: 1, Event: \($0)") })
delay(5) {
_ = interval
.subscribe(onNext: { print("Subscription: 2, Event: \($0)") })
}
}
//sampleWithoutConnectableOperators() // Uncomment to run this example; comment to stop running
/*:
> `interval` creates an `Observable` sequence that emits elements after each `period`, on the specified scheduler. [More info](http://reactivex.io/documentation/operators/interval.html)
![](http://reactivex.io/documentation/operators/images/interval.c.png)
----
## `publish`
Converts the source `Observable` sequence into a connectable sequence. [More info](http://reactivex.io/documentation/operators/publish.html)
![](http://reactivex.io/documentation/operators/images/publishConnect.c.png)
*/
func sampleWithPublish() {
printExampleHeader(#function)
let intSequence = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
.publish()
_ = intSequence
.subscribe(onNext: { print("Subscription 1:, Event: \($0)") })
delay(2) { _ = intSequence.connect() }
delay(4) {
_ = intSequence
.subscribe(onNext: { print("Subscription 2:, Event: \($0)") })
}
delay(6) {
_ = intSequence
.subscribe(onNext: { print("Subscription 3:, Event: \($0)") })
}
}
//sampleWithPublish() // Uncomment to run this example; comment to stop running
//: > Schedulers are an abstraction of mechanisms for performing work, such as on specific threads or dispatch queues. [More info](https://github.com/ReactiveX/RxSwift/blob/master/Documentation/Schedulers.md)
/*:
----
## `replay`
Converts the source `Observable` sequence into a connectable sequence, and will replay `bufferSize` number of previous emissions to each new subscriber. [More info](http://reactivex.io/documentation/operators/replay.html)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/replay.png)
*/
func sampleWithReplayBuffer() {
printExampleHeader(#function)
let intSequence = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
.replay(5)
_ = intSequence
.subscribe(onNext: { print("Subscription 1:, Event: \($0)") })
delay(2) { _ = intSequence.connect() }
delay(4) {
_ = intSequence
.subscribe(onNext: { print("Subscription 2:, Event: \($0)") })
}
delay(8) {
_ = intSequence
.subscribe(onNext: { print("Subscription 3:, Event: \($0)") })
}
}
// sampleWithReplayBuffer() // Uncomment to run this example; comment to stop running
/*:
----
## `multicast`
Converts the source `Observable` sequence into a connectable sequence, and broadcasts its emissions via the specified `subject`.
*/
func sampleWithMulticast() {
printExampleHeader(#function)
let subject = PublishSubject<Int>()
_ = subject
.subscribe(onNext: { print("Subject: \($0)") })
let intSequence = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
.multicast(subject)
_ = intSequence
.subscribe(onNext: { print("\tSubscription 1:, Event: \($0)") })
delay(2) { _ = intSequence.connect() }
delay(4) {
_ = intSequence
.subscribe(onNext: { print("\tSubscription 2:, Event: \($0)") })
}
delay(6) {
_ = intSequence
.subscribe(onNext: { print("\tSubscription 3:, Event: \($0)") })
}
}
//sampleWithMulticast() // Uncomment to run this example; comment to stop running
//: [Next](@next) - [Table of Contents](Table_of_Contents)

View File

@ -0,0 +1,212 @@
/*:
> # IMPORTANT: To use **Rx.playground**:
1. Open **Rx.xcworkspace**.
1. Build the **RxSwift-OSX** scheme (**Product** **Build**).
1. Open **Rx** playground in the **Project navigator**.
1. Show the Debug Area (**View** **Debug Area** **Show Debug Area**).
----
[Previous](@previous) - [Table of Contents](Table_of_Contents)
*/
import RxSwift
/*:
# Creating and Subscribing to `Observable`s
There are several ways to create and subscribe to `Observable` sequences.
## never
Creates a sequence that never terminates and never emits any events. [More info](http://reactivex.io/documentation/operators/empty-never-throw.html)
*/
example("never") {
let disposeBag = DisposeBag()
let neverSequence = Observable<String>.never()
let neverSequenceSubscription = neverSequence
.subscribe { _ in
print("This will never be printed")
}
neverSequenceSubscription.addDisposableTo(disposeBag)
}
/*:
----
## empty
Creates an empty `Observable` sequence that only emits a Completed event. [More info](http://reactivex.io/documentation/operators/empty-never-throw.html)
*/
example("empty") {
let disposeBag = DisposeBag()
Observable<Int>.empty()
.subscribe { event in
print(event)
}
.addDisposableTo(disposeBag)
}
/*:
> This example also introduces chaining together creating and subscribing to an `Observable` sequence.
----
## just
Creates an `Observable` sequence with a single element. [More info](http://reactivex.io/documentation/operators/just.html)
*/
example("just") {
let disposeBag = DisposeBag()
Observable.just("🔴")
.subscribe { event in
print(event)
}
.addDisposableTo(disposeBag)
}
/*:
----
## of
Creates an `Observable` sequence with a fixed number of elements.
*/
example("of") {
let disposeBag = DisposeBag()
Observable.of("🐶", "🐱", "🐭", "🐹")
.subscribe(onNext: { element in
print(element)
})
.addDisposableTo(disposeBag)
}
/*:
> This example also introduces using the `subscribe(onNext:)` convenience method. Unlike `subscribe(_:)`, which subscribes an _event_ handler for all event types (Next, Error, and Completed), `subscribe(onNext:)` subscribes an _element_ handler that will ignore Error and Completed events and only produce Next event elements. There are also `subscribe(onError:)` and `subscribe(onCompleted:)` convenience methods, should you only want to subscribe to those event types. And there is a `subscribe(onNext:onError:onCompleted:onDisposed:)` method, which allows you to react to one or more event types and when the subscription is terminated for any reason, or disposed, in a single call:
```
someObservable.subscribe(
onNext: { print("Element:", $0) },
onError: { print("Error:", $0) },
onCompleted: { print("Completed") },
onDisposed: { print("Disposed") }
)
```
----
## from
Creates an `Observable` sequence from a `SequenceType`, such as an `Array`, `Dictionary`, or `Set`.
*/
example("from") {
let disposeBag = DisposeBag()
Observable.from(["🐶", "🐱", "🐭", "🐹"])
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}
/*:
> This example also demonstrates using the default argument name `$0` instead of explicitly naming the argument.
----
## create
Creates a custom `Observable` sequence. [More info](http://reactivex.io/documentation/operators/create.html)
*/
example("create") {
let disposeBag = DisposeBag()
let myJust = { (element: String) -> Observable<String> in
return Observable.create { observer in
observer.on(.next(element))
observer.on(.completed)
return Disposables.create()
}
}
myJust("🔴")
.subscribe { print($0) }
.addDisposableTo(disposeBag)
}
/*:
----
## range
Creates an `Observable` sequence that emits a range of sequential integers and then terminates. [More info](http://reactivex.io/documentation/operators/range.html)
*/
example("range") {
let disposeBag = DisposeBag()
Observable.range(start: 1, count: 10)
.subscribe { print($0) }
.addDisposableTo(disposeBag)
}
/*:
----
## repeatElement
Creates an `Observable` sequence that emits the given element indefinitely. [More info](http://reactivex.io/documentation/operators/repeat.html)
*/
example("repeatElement") {
let disposeBag = DisposeBag()
Observable.repeatElement("🔴")
.take(3)
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}
/*:
> This example also introduces using the `take` operator to return a specified number of elements from the start of a sequence.
----
## generate
Creates an `Observable` sequence that generates values for as long as the provided condition evaluates to `true`.
*/
example("generate") {
let disposeBag = DisposeBag()
Observable.generate(
initialState: 0,
condition: { $0 < 3 },
iterate: { $0 + 1 }
)
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}
/*:
----
## deferred
Creates a new `Observable` sequence for each subscriber. [More info](http://reactivex.io/documentation/operators/defer.html)
*/
example("deferred") {
let disposeBag = DisposeBag()
var count = 1
let deferredSequence = Observable<String>.deferred {
print("Creating \(count)")
count += 1
return Observable.create { observer in
print("Emitting...")
observer.onNext("🐶")
observer.onNext("🐱")
observer.onNext("🐵")
return Disposables.create()
}
}
deferredSequence
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
deferredSequence
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}
/*:
----
## error
Creates an `Observable` sequence that emits no items and immediately terminates with an error.
*/
example("error") {
let disposeBag = DisposeBag()
Observable<Int>.error(TestError.test)
.subscribe { print($0) }
.addDisposableTo(disposeBag)
}
/*:
----
## doOn
Invokes a side-effect action for each emitted event and returns (passes through) the original event. [More info](http://reactivex.io/documentation/operators/do.html)
*/
example("doOn") {
let disposeBag = DisposeBag()
Observable.of("🍎", "🍐", "🍊", "🍋")
.do(onNext: { print("Intercepted:", $0) }, onError: { print("Intercepted error:", $0) }, onCompleted: { print("Completed") })
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}
//: > There are also `doOnNext(_:)`, `doOnError(_:)`, and `doOnCompleted(_:)` convenience methods to intercept those specific events, and `doOn(onNext:onError:onCompleted:)` to intercept one or more events in a single call.
//: [Next](@next) - [Table of Contents](Table_of_Contents)

View File

@ -0,0 +1,83 @@
/*:
> # IMPORTANT: To use **Rx.playground**:
1. Open **Rx.xcworkspace**.
1. Build the **RxSwift-OSX** scheme (**Product** **Build**).
1. Open **Rx** playground in the **Project navigator**.
1. Show the Debug Area (**View** **Debug Area** **Show Debug Area**).
----
[Previous](@previous) - [Table of Contents](Table_of_Contents)
*/
import RxSwift
/*:
# Debugging Operators
Operators to help debug Rx code.
## `debug`
Prints out all subscriptions, events, and disposals.
*/
example("debug") {
let disposeBag = DisposeBag()
var count = 1
let sequenceThatErrors = Observable<String>.create { observer in
observer.onNext("🍎")
observer.onNext("🍐")
observer.onNext("🍊")
if count < 5 {
observer.onError(TestError.test)
print("Error encountered")
count += 1
}
observer.onNext("🐶")
observer.onNext("🐱")
observer.onNext("🐭")
observer.onCompleted()
return Disposables.create()
}
sequenceThatErrors
.retry(3)
.debug()
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}
/*:
----
## `RxSwift.resourceCount`
Provides a count of all Rx resource allocations, which is useful for detecting leaks during development.
*/
#if NOT_IN_PLAYGROUND
#else
example("RxSwift.resourceCount") {
print(RxSwift.resourceCount)
let disposeBag = DisposeBag()
print(RxSwift.resourceCount)
let variable = Variable("🍎")
let subscription1 = variable.asObservable().subscribe(onNext: { print($0) })
print(RxSwift.resourceCount)
let subscription2 = variable.asObservable().subscribe(onNext: { print($0) })
print(RxSwift.resourceCount)
subscription1.dispose()
print(RxSwift.resourceCount)
subscription2.dispose()
print(RxSwift.resourceCount)
}
print(RxSwift.resourceCount)
#endif
//: > `RxSwift.resourceCount` is not enabled by default, and should generally not be enabled in Release builds. [Click here](Enable_RxSwift.resourceCount) for instructions on how to enable it.
//: [Next](@next) - [Table of Contents](Table_of_Contents)

View File

@ -0,0 +1,30 @@
//: [Back](@previous)
/*:
Follow these instructions to enable `RxSwift.resourceCount` in your project:
#
**CocoaPods**
1. Add a `post_install` hook to your Podfile, e.g.:
```
target 'AppTarget' do
pod 'RxSwift'
end
post_install do |installer|
installer.pods_project.targets.each do |target|
if target.name == 'RxSwift'
target.build_configurations.each do |config|
if config.name == 'Debug'
config.build_settings['OTHER_SWIFT_FLAGS'] ||= ['-D', 'TRACE_RESOURCES']
end
end
end
end
end
```
2. Run `pod update`.
3. Build project (**Product** **Build**).
#
**Carthage**
1. Run `carthage build --configuration Debug`.
2. Build project (**Product** **Build**).
*/

View File

@ -1,103 +1,131 @@
/*:
> # IMPORTANT: To use `Rx.playground`, please:
1. Open `Rx.xcworkspace`
2. Build `RxSwift-OSX` scheme
3. And then open `Rx` playground in `Rx.xcworkspace` tree view.
4. Choose `View > Show Debug Area`
*/
//: [<< Previous](@previous) - [Index](Index)
> # IMPORTANT: To use **Rx.playground**:
1. Open **Rx.xcworkspace**.
1. Build the **RxSwift-OSX** scheme (**Product** **Build**).
1. Open **Rx** playground in the **Project navigator**.
1. Show the Debug Area (**View** **Debug Area** **Show Debug Area**).
----
[Previous](@previous) - [Table of Contents](Table_of_Contents)
*/
import RxSwift
import Foundation
/*:
## Error Handling Operators
# Error Handling Operators
Operators that help to recover from error notifications from an Observable.
*/
/*:
### `catchError`
Recover from an `Error` notification by continuing the sequence without error
## `catchErrorJustReturn`
Recovers from an Error event by returning an `Observable` sequence that emits a single element and then terminates. [More info](http://reactivex.io/documentation/operators/catch.html)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/catch.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/catch.html )
*/
example("catchError 1") {
let sequenceThatFails = PublishSubject<Int>()
let recoverySequence = Observable.of(100, 200, 300, 400)
_ = sequenceThatFails
.catchError { error in
example("catchErrorJustReturn") {
let disposeBag = DisposeBag()
let sequenceThatFails = PublishSubject<String>()
sequenceThatFails
.catchErrorJustReturn("😊")
.subscribe { print($0) }
.addDisposableTo(disposeBag)
sequenceThatFails.onNext("😬")
sequenceThatFails.onNext("😨")
sequenceThatFails.onNext("😡")
sequenceThatFails.onNext("🔴")
sequenceThatFails.onError(TestError.test)
}
/*:
----
## `catchError`
Recovers from an Error event by switching to the provided recovery `Observable` sequence. [More info](http://reactivex.io/documentation/operators/catch.html)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/catch.png)
*/
example("catchError") {
let disposeBag = DisposeBag()
let sequenceThatFails = PublishSubject<String>()
let recoverySequence = PublishSubject<String>()
sequenceThatFails
.catchError {
print("Error:", $0)
return recoverySequence
}
.subscribe {
print($0)
}
sequenceThatFails.on(.Next(1))
sequenceThatFails.on(.Next(2))
sequenceThatFails.on(.Next(3))
sequenceThatFails.on(.Next(4))
sequenceThatFails.on(.Error(NSError(domain: "Test", code: 0, userInfo: nil)))
.subscribe { print($0) }
.addDisposableTo(disposeBag)
sequenceThatFails.onNext("😬")
sequenceThatFails.onNext("😨")
sequenceThatFails.onNext("😡")
sequenceThatFails.onNext("🔴")
sequenceThatFails.onError(TestError.test)
recoverySequence.onNext("😊")
}
example("catchError 2") {
let sequenceThatFails = PublishSubject<Int>()
_ = sequenceThatFails
.catchErrorJustReturn(100)
.subscribe {
print($0)
}
sequenceThatFails.on(.Next(1))
sequenceThatFails.on(.Next(2))
sequenceThatFails.on(.Next(3))
sequenceThatFails.on(.Next(4))
sequenceThatFails.on(.Error(NSError(domain: "Test", code: 0, userInfo: nil)))
}
/*:
### `retry`
If a source Observable emits an error, resubscribe to it in the hopes that it will complete without error
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/retry.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/retry.html )
*/
----
## `retry`
Recovers repeatedly Error events by resubscribing to the `Observable` sequence, indefinitely. [More info](http://reactivex.io/documentation/operators/retry.html)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/retry.png)
*/
example("retry") {
var count = 1 // bad practice, only for example purposes
let funnyLookingSequence = Observable<Int>.create { observer in
let error = NSError(domain: "Test", code: 0, userInfo: nil)
observer.on(.Next(0))
observer.on(.Next(1))
observer.on(.Next(2))
if count < 2 {
observer.on(.Error(error))
let disposeBag = DisposeBag()
var count = 1
let sequenceThatErrors = Observable<String>.create { observer in
observer.onNext("🍎")
observer.onNext("🍐")
observer.onNext("🍊")
if count == 1 {
observer.onError(TestError.test)
print("Error encountered")
count += 1
}
observer.on(.Next(3))
observer.on(.Next(4))
observer.on(.Next(5))
observer.on(.Completed)
return NopDisposable.instance
observer.onNext("🐶")
observer.onNext("🐱")
observer.onNext("🐭")
observer.onCompleted()
return Disposables.create()
}
_ = funnyLookingSequence
sequenceThatErrors
.retry()
.subscribe {
print($0)
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}
/*:
----
## `retry(_:)`
Recovers repeatedly from Error events by resubscribing to the `Observable` sequence, up to `maxAttemptCount` number of retries. [More info](http://reactivex.io/documentation/operators/retry.html)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/retry.png)
*/
example("retry maxAttemptCount") {
let disposeBag = DisposeBag()
var count = 1
let sequenceThatErrors = Observable<String>.create { observer in
observer.onNext("🍎")
observer.onNext("🍐")
observer.onNext("🍊")
if count < 5 {
observer.onError(TestError.test)
print("Error encountered")
count += 1
}
observer.onNext("🐶")
observer.onNext("🐱")
observer.onNext("🐭")
observer.onCompleted()
return Disposables.create()
}
sequenceThatErrors
.retry(3)
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}
//: [Index](Index) - [Next >>](@next)
//: [Next](@next) - [Table of Contents](Table_of_Contents)

View File

@ -1,78 +0,0 @@
/*:
> # IMPORTANT: To use `Rx.playground`, please:
1. Open `Rx.xcworkspace`
2. Build `RxSwift-OSX` scheme
3. And then open `Rx` playground in `Rx.xcworkspace` tree view.
4. Choose `View > Show Debug Area`
*/
//: [<< Previous](@previous) - [Index](Index)
import RxSwift
/*:
## Filtering Observables
Operators that selectively emit items from a source Observable.
*/
/*:
### `filter`
Emit only those items from an Observable that pass a predicate test
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/filter.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/filter.html )
*/
example("filter") {
let subscription = Observable.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
.filter {
$0 % 2 == 0
}
.subscribe {
print($0)
}
}
/*:
### `distinctUntilChanged`
Suppress duplicate items emitted by an Observable
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/distinct.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/distinct.html )
*/
example("distinctUntilChanged") {
let subscription = Observable.of(1, 2, 3, 1, 1, 4)
.distinctUntilChanged()
.subscribe {
print($0)
}
}
/*:
### `take`
Emit only the first n items emitted by an Observable
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/take.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/take.html )
*/
example("take") {
let subscription = Observable.of(1, 2, 3, 4, 5, 6)
.take(3)
.subscribe {
print($0)
}
}
//: [Index](Index) - [Next >>](@next)

View File

@ -0,0 +1,231 @@
/*:
> # IMPORTANT: To use **Rx.playground**:
1. Open **Rx.xcworkspace**.
1. Build the **RxSwift-OSX** scheme (**Product** **Build**).
1. Open **Rx** playground in the **Project navigator**.
1. Show the Debug Area (**View** **Debug Area** **Show Debug Area**).
----
[Previous](@previous) - [Table of Contents](Table_of_Contents)
*/
import RxSwift
/*:
# Filtering and Conditional Operators
Operators that selectively emit elements from a source `Observable` sequence.
## `filter`
Emits only those elements from an `Observable` sequence that meet the specified condition. [More info](http://reactivex.io/documentation/operators/filter.html)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/filter.png)
*/
example("filter") {
let disposeBag = DisposeBag()
Observable.of(
"🐱", "🐰", "🐶",
"🐸", "🐱", "🐰",
"🐹", "🐸", "🐱")
.filter {
$0 == "🐱"
}
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}
/*:
----
## `distinctUntilChanged`
Suppresses sequential duplicate elements emitted by an `Observable` sequence. [More info](http://reactivex.io/documentation/operators/distinct.html)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/distinct.png)
*/
example("distinctUntilChanged") {
let disposeBag = DisposeBag()
Observable.of("🐱", "🐷", "🐱", "🐱", "🐱", "🐵", "🐱")
.distinctUntilChanged()
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}
/*:
----
## `elementAt`
Emits only the element at the specified index of all elements emitted by an `Observable` sequence. [More info](http://reactivex.io/documentation/operators/elementat.html)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/elementat.png)
*/
example("elementAt") {
let disposeBag = DisposeBag()
Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵")
.elementAt(3)
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}
/*:
----
## `single`
Emits only the first element (or the first element that meets a condition) emitted by an `Observable` sequence. Will throw an error if the `Observable` sequence does not emit exactly one element.
*/
example("single") {
let disposeBag = DisposeBag()
Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵")
.single()
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}
example("single with conditions") {
let disposeBag = DisposeBag()
Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵")
.single { $0 == "🐸" }
.subscribe { print($0) }
.addDisposableTo(disposeBag)
Observable.of("🐱", "🐰", "🐶", "🐱", "🐰", "🐶")
.single { $0 == "🐰" }
.subscribe { print($0) }
.addDisposableTo(disposeBag)
Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵")
.single { $0 == "🔵" }
.subscribe { print($0) }
.addDisposableTo(disposeBag)
}
/*:
----
## `take`
Emits only the specified number of elements from the beginning of an `Observable` sequence. [More info](http://reactivex.io/documentation/operators/take.html)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/take.png)
*/
example("take") {
let disposeBag = DisposeBag()
Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵")
.take(3)
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}
/*:
----
## `takeLast`
Emits only the specified number of elements from the end of an `Observable` sequence. [More info](http://reactivex.io/documentation/operators/takelast.html)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/takelast.png)
*/
example("takeLast") {
let disposeBag = DisposeBag()
Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵")
.takeLast(3)
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}
/*:
----
## `takeWhile`
Emits elements from the beginning of an `Observable` sequence as long as the specified condition evaluates to `true`. [More info](http://reactivex.io/documentation/operators/takewhile.html)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/takewhile.png)
*/
example("takeWhile") {
let disposeBag = DisposeBag()
Observable.of(1, 2, 3, 4, 5, 6)
.takeWhile { $0 < 4 }
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}
/*:
----
## `takeUntil`
Emits elements from a source `Observable` sequence until a reference `Observable` sequence emits an element. [More info](http://reactivex.io/documentation/operators/takeuntil.html)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/takeuntil.png)
*/
example("takeUntil") {
let disposeBag = DisposeBag()
let sourceSequence = PublishSubject<String>()
let referenceSequence = PublishSubject<String>()
sourceSequence
.takeUntil(referenceSequence)
.subscribe { print($0) }
.addDisposableTo(disposeBag)
sourceSequence.onNext("🐱")
sourceSequence.onNext("🐰")
sourceSequence.onNext("🐶")
referenceSequence.onNext("🔴")
sourceSequence.onNext("🐸")
sourceSequence.onNext("🐷")
sourceSequence.onNext("🐵")
}
/*:
----
## `skip`
Suppresses emitting the specified number of elements from the beginning of an `Observable` sequence. [More info](http://reactivex.io/documentation/operators/skip.html)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/skip.png)
*/
example("skip") {
let disposeBag = DisposeBag()
Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵")
.skip(2)
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}
/*:
----
## `skipWhile`
Suppresses emitting the elements from the beginning of an `Observable` sequence that meet the specified condition. [More info](http://reactivex.io/documentation/operators/skipwhile.html)
![](http://reactivex.io/documentation/operators/images/skipWhile.c.png)
*/
example("skipWhile") {
let disposeBag = DisposeBag()
Observable.of(1, 2, 3, 4, 5, 6)
.skipWhile { $0 < 4 }
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}
/*:
----
## `skipWhileWithIndex`
Suppresses emitting the elements from the beginning of an `Observable` sequence that meet the specified condition, and emits the remaining elements. The closure is also passed each element's index.
*/
example("skipWhileWithIndex") {
let disposeBag = DisposeBag()
Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵")
.skipWhileWithIndex { element, index in
index < 3
}
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}
/*:
----
## `skipUntil`
Suppresses emitting the elements from a source `Observable` sequence until a reference `Observable` sequence emits an element. [More info](http://reactivex.io/documentation/operators/skipuntil.html)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/skipuntil.png)
*/
example("skipUntil") {
let disposeBag = DisposeBag()
let sourceSequence = PublishSubject<String>()
let referenceSequence = PublishSubject<String>()
sourceSequence
.skipUntil(referenceSequence)
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
sourceSequence.onNext("🐱")
sourceSequence.onNext("🐰")
sourceSequence.onNext("🐶")
referenceSequence.onNext("🔴")
sourceSequence.onNext("🐸")
sourceSequence.onNext("🐷")
sourceSequence.onNext("🐵")
}
//: [Next](@next) - [Table of Contents](Table_of_Contents)

View File

@ -1,27 +0,0 @@
/*:
> # IMPORTANT: To use `Rx.playground`, please:
1. Open `Rx.xcworkspace`
2. Build `RxSwift-OSX` scheme
3. And then open `Rx` playground in `Rx.xcworkspace` tree view.
4. Choose `View > Show Debug Area`
*/
/*:
## Index:
1. [Introduction](Introduction)
1. [Subjects](Subjects)
1. [Transforming Observables](Transforming_Observables)
1. [Filtering Observables](Filtering_Observables)
1. [Combining Observables](Combining_Observables)
1. [Error Handling Operators](Error_Handling_Operators)
1. [Observable Utility Operators](Observable_Utility_Operators)
1. [Conditional and Boolean Operators](Conditional_and_Boolean_Operators)
1. [Mathematical and Aggregate Operators](Mathematical_and_Aggregate_Operators)
1. [Connectable Observable Operators](Connectable_Observable_Operators)
*/
//: [Index](Index) - [Next >>](@next)

View File

@ -1,198 +1,85 @@
/*:
> # IMPORTANT: To use `Rx.playground`, please:
1. Open `Rx.xcworkspace`
2. Build `RxSwift-OSX` scheme
3. And then open `Rx` playground in `Rx.xcworkspace` tree view.
4. Choose `View > Show Debug Area`
*/
//: [<< Index](@previous)
> # IMPORTANT: To use **Rx.playground**:
1. Open **Rx.xcworkspace**.
1. Build the **RxSwift-OSX** scheme (**Product** **Build**).
1. Open **Rx** playground in the **Project navigator**.
1. Show the Debug Area (**View** **Debug Area** **Show Debug Area**).
----
[Previous](@previous)
*/
import RxSwift
import Foundation
/*:
# Introduction
## Why use RxSwift?
A vast majority of the code we write revolves around responding to external actions. When a user manipulates a control, we need to write an @IBAction to respond to that. We need to observe Notifications to detect when the keyboard changes position. We must provide blocks to execute when URL Sessions respond with data. And we use KVO to detect changes in variables.
A vast majority of the code we write involves responding to external events. When a user manipulates a control, we need to write an `@IBAction` handler to respond. We need to observe notifications to detect when the keyboard changes position. We must provide closures to execute when URL sessions respond with data. And we use KVO to detect changes to variables.
All of these various systems makes our code needlessly complex. Wouldn't it be better if there was one consistent system that handled all of our call/response code? Rx is such a system.
## Observables
The key to understanding RxSwift is in understanding the notion of Observables. Creating them, manipulating them, and subscribing to them in order to react to changes.
## Creating and Subscribing to Observables
The first step in understanding this library is in understanding how to create Observables. There are a number of functions available to make Observables.
Creating an Observable is one thing, but if nothing subscribes to the observable, then nothing will come of it so both are explained simultaneously.
RxSwift is the official implementation of [Reactive Extensions](http://reactivex.io) (aka Rx), which exist for [most major languages and platforms](http://reactivex.io/languages.html).
*/
/*:
### empty
`empty` creates an empty sequence. The only message it sends is the `.Completed` message.
*/
example("empty") {
let emptySequence = Observable<Int>.empty()
let subscription = emptySequence
.subscribe { event in
print(event)
}
}
## Concepts
**Every `Observable` instance is just a sequence.**
The key advantage for an `Observable` sequence vs. Swift's `SequenceType` is that it can also receive elements asynchronously. _This is the essence of RxSwift._ Everything else expands upon this concept.
* An `Observable` (`ObservableType`) is equivalent to a `SequenceType`.
* The `ObservableType.subscribe(_:)` method is equivalent to `SequenceType.generate()`.
* `ObservableType.subscribe(_:)` takes an observer (`ObserverType`) parameter, which will be subscribed to automatically receive sequence events and elements emitted by the `Observable`, instead of manually calling `next()` on the returned generator.
*/
/*:
### never
`never` creates a sequence that never sends any element or completes.
If an `Observable` emits a next event (`Event.next(Element)`), it can continue to emit more events. However, if the `Observable` emits either an error event (`Event.error(ErrorType)`) or a completed event (`Event.completed`), the `Observable` sequence cannot emit additional events to the subscriber.
Sequence grammar explains this more concisely:
`next* (error | completed)?`
And this can also be explained more visually using diagrams:
`--1--2--3--4--5--6--|----> // "|" = Terminates normally`
`--a--b--c--d--e--f--X----> // "X" = Terminates with an error`
`--tap--tap----------tap--> // "|" = Continues indefinitely, such as a sequence of button taps`
> These diagrams are called marble diagrams. You can learn more about them at [RxMarbles.com](http://rxmarbles.com).
*/
example("never") {
let neverSequence = Observable<Int>.never()
let subscription = neverSequence
.subscribe { _ in
print("This block is never called.")
}
}
/*:
### just
`just` represents sequence that contains one element. It sends two messages to subscribers. The first message is the value of single element and the second message is `.Completed`.
*/
example("just") {
let singleElementSequence = Observable.just(32)
let subscription = singleElementSequence
.subscribe { event in
print(event)
}
}
/*:
### sequenceOf
`sequenceOf` creates a sequence of a fixed number of elements.
*/
example("sequenceOf") {
let sequenceOfElements/* : Observable<Int> */ = Observable.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
let subscription = sequenceOfElements
.subscribe { event in
print(event)
}
}
/*:
### from
`from` creates a sequence from `SequenceType`
*/
example("toObservable") {
let sequenceFromArray = [1, 2, 3, 4, 5].toObservable()
let subscription = sequenceFromArray
.subscribe { event in
print(event)
}
}
/*:
### create
`create` creates sequence using Swift closure. This examples creates custom version of `just` operator.
*/
example("create") {
let myJust = { (singleElement: Int) -> Observable<Int> in
return Observable.create { observer in
observer.on(.Next(singleElement))
observer.on(.Completed)
return NopDisposable.instance
}
### Observables and observers (aka subscribers)
`Observable`s will not execute their subscription closure unless there is a subscriber. In the following example, the closure of the `Observable` will never be executed, because there are no subscribers:
*/
example("Observable with no subscribers") {
_ = Observable<String>.create { observerOfString -> Disposable in
print("This will never be printed")
observerOfString.on(.next("😬"))
observerOfString.on(.completed)
return Disposables.create()
}
let subscription = myJust(5)
.subscribe { event in
print(event)
}
}
/*:
### generate
`generate` creates sequence that generates its values and determines when to terminate based on its previous values.
*/
example("generate") {
let generated = Observable.generate(
initialState: 0,
condition: { $0 < 3 },
iterate: { $0 + 1 }
)
let subscription = generated
.subscribe { event in
print(event)
----
In the following example, the closure will be executed when `subscribe(_:)` is called:
*/
example("Observable with subscriber") {
_ = Observable<String>.create { observerOfString in
print("Observable created")
observerOfString.on(.next("😉"))
observerOfString.on(.completed)
return Disposables.create()
}
}
/*:
### failWith
create an Observable that emits no items and terminates with an error
*/
example("failWith") {
let error = NSError(domain: "Test", code: -1, userInfo: nil)
let erroredSequence = Observable<Int>.error(error)
let subscription = erroredSequence
.subscribe { event in
print(event)
}
}
/*:
### `deferred`
do not create the Observable until the observer subscribes, and create a fresh Observable for each observer
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/defer.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/defer.html )
*/
example("deferred") {
let deferredSequence: Observable<Int> = Observable.deferred {
print("creating")
return Observable.create { observer in
print("emmiting")
observer.on(.Next(0))
observer.on(.Next(1))
observer.on(.Next(2))
return NopDisposable.instance
}
}
_ = deferredSequence
.subscribe { event in
print(event)
}
_ = deferredSequence
.subscribe { event in
print(event)
}
}
/*:
There is a lot more useful methods in the RxCocoa library, so check them out:
* `rx_observe` exist on every NSObject and wraps KVO.
* `rx_tap` exists on buttons and wraps @IBActions
* `rx_notification` wraps NotificationCenter events
* ... and many others
*/
> Don't concern yourself with the details of how these `Observable`s were created in these examples. We'll get into that [next](@next).
#
> `subscribe(_:)` returns a `Disposable` instance that represents a disposable resource such as a subscription. It was ignored in the previous simple example, but it should normally be properly handled. This usually means adding it to a `DisposeBag` instance. All examples going forward will include proper handling, because, well, practice makes _permanent_ 🙂. You can learn more about this in the [Disposing section](https://github.com/ReactiveX/RxSwift/blob/master/Documentation/GettingStarted.md#disposing) of the [Getting Started guide](https://github.com/ReactiveX/RxSwift/blob/master/Documentation/GettingStarted.md).
*/
//: [Index](Index) - [Next >>](@next)
//: [Next](@next) - [Table of Contents](Table_of_Contents)

View File

@ -1,86 +1,72 @@
/*:
> # IMPORTANT: To use `Rx.playground`, please:
1. Open `Rx.xcworkspace`
2. Build `RxSwift-OSX` scheme
3. And then open `Rx` playground in `Rx.xcworkspace` tree view.
4. Choose `View > Show Debug Area`
*/
//: [<< Previous](@previous) - [Index](Index)
> # IMPORTANT: To use **Rx.playground**:
1. Open **Rx.xcworkspace**.
1. Build the **RxSwift-OSX** scheme (**Product** **Build**).
1. Open **Rx** playground in the **Project navigator**.
1. Show the Debug Area (**View** **Debug Area** **Show Debug Area**).
----
[Previous](@previous) - [Table of Contents](Table_of_Contents)
*/
import RxSwift
/*:
## Mathematical and Aggregate Operators
Operators that operate on the entire sequence of items emitted by an Observable
*/
/*:
### `concat`
Emit the emissions from two or more Observables without interleaving them.
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/concat.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/concat.html )
*/
example("concat") {
let var1 = BehaviorSubject(value: 0)
let var2 = BehaviorSubject(value: 200)
# Mathematical and Aggregate Operators
Operators that operate on the entire sequence of items emitted by an `Observable`.
## `toArray`
Converts an `Observable` sequence into an array, emits that array as a new single-element `Observable` sequence, and then terminates. [More info](http://reactivex.io/documentation/operators/to.html)
![](http://reactivex.io/documentation/operators/images/to.c.png)
*/
example("toArray") {
let disposeBag = DisposeBag()
// var3 is like an Observable<Observable<Int>>
let var3 = BehaviorSubject(value: var1)
let d = var3
.concat()
.subscribe {
print($0)
}
var1.on(.Next(1))
var1.on(.Next(2))
var1.on(.Next(3))
var1.on(.Next(4))
var3.on(.Next(var2))
var2.on(.Next(201))
var1.on(.Next(5))
var1.on(.Next(6))
var1.on(.Next(7))
var1.on(.Completed)
var2.on(.Next(202))
var2.on(.Next(203))
var2.on(.Next(204))
Observable.range(start: 1, count: 10)
.toArray()
.subscribe { print($0) }
.addDisposableTo(disposeBag)
}
/*:
### `reduce`
Apply a function to each item emitted by an Observable, sequentially, and emit the final value.
This function will perform a function on each element in the sequence until it is completed, then send a message with the aggregate value. It works much like the Swift `reduce` function works on sequences.
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/reduce.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/reduce.html )
*/
----
## `reduce`
Begins with an initial seed value, and then applies an accumulator closure to all elements emitted by an `Observable` sequence, and returns the aggregate result as a single-element `Observable` sequence. [More info](http://reactivex.io/documentation/operators/reduce.html)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/reduce.png)
*/
example("reduce") {
_ = Observable.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
.reduce(0, accumulator: +)
.subscribe {
print($0)
}
let disposeBag = DisposeBag()
Observable.of(10, 100, 1000)
.reduce(1, accumulator: +)
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}
/*:
----
## `concat`
Joins elements from inner `Observable` sequences of an `Observable` sequence in a sequential manner, waiting for each sequence to terminate successfully before emitting elements from the next sequence. [More info](http://reactivex.io/documentation/operators/concat.html)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/concat.png)
*/
example("concat") {
let disposeBag = DisposeBag()
let subject1 = BehaviorSubject(value: "🍎")
let subject2 = BehaviorSubject(value: "🐶")
let variable = Variable(subject1)
variable.asObservable()
.concat()
.subscribe { print($0) }
.addDisposableTo(disposeBag)
subject1.onNext("🍐")
subject1.onNext("🍊")
variable.value = subject2
subject2.onNext("I would be ignored")
subject2.onNext("🐱")
subject1.onCompleted()
subject2.onNext("🐭")
}
//: [Index](Index) - [Next >>](@next)
//: [Next](@next) - [Table of Contents](Table_of_Contents)

View File

@ -1,122 +0,0 @@
/*:
> # IMPORTANT: To use `Rx.playground`, please:
1. Open `Rx.xcworkspace`
2. Build `RxSwift-OSX` scheme
3. And then open `Rx` playground in `Rx.xcworkspace` tree view.
4. Choose `View > Show Debug Area`
*/
//: [<< Previous](@previous) - [Index](Index)
import RxSwift
import Foundation
/*:
## Observable Utility Operators
A toolbox of useful Operators for working with Observables.
*/
/*:
### `subscribe`
[More info in reactive.io website]( http://reactivex.io/documentation/operators/subscribe.html )
*/
example("subscribe") {
let sequenceOfInts = PublishSubject<Int>()
_ = sequenceOfInts
.subscribe {
print($0)
}
sequenceOfInts.on(.Next(1))
sequenceOfInts.on(.Completed)
}
/*:
There are several variants of the `subscribe` operator.
*/
/*:
### `subscribeNext`
*/
example("subscribeNext") {
let sequenceOfInts = PublishSubject<Int>()
_ = sequenceOfInts
.subscribeNext {
print($0)
}
sequenceOfInts.on(.Next(1))
sequenceOfInts.on(.Completed)
}
/*:
### `subscribeCompleted`
*/
example("subscribeCompleted") {
let sequenceOfInts = PublishSubject<Int>()
_ = sequenceOfInts
.subscribeCompleted {
print("It's completed")
}
sequenceOfInts.on(.Next(1))
sequenceOfInts.on(.Completed)
}
/*:
### `subscribeError`
*/
example("subscribeError") {
let sequenceOfInts = PublishSubject<Int>()
_ = sequenceOfInts
.subscribeError { error in
print(error)
}
sequenceOfInts.on(.Next(1))
sequenceOfInts.on(.Error(NSError(domain: "Examples", code: -1, userInfo: nil)))
}
/*:
### `doOn`
register an action to take upon a variety of Observable lifecycle events
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/do.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/do.html )
*/
example("doOn") {
let sequenceOfInts = PublishSubject<Int>()
_ = sequenceOfInts
.doOn {
print("Intercepted event \($0)")
}
.subscribe {
print($0)
}
sequenceOfInts.on(.Next(1))
sequenceOfInts.on(.Completed)
}
//: [Index](Index) - [Next >>](@next)

View File

@ -1,113 +0,0 @@
/*:
> # IMPORTANT: To use `Rx.playground`, please:
1. Open `Rx.xcworkspace`
2. Build `RxSwift-OSX` scheme
3. And then open `Rx` playground in `Rx.xcworkspace` tree view.
4. Choose `View > Show Debug Area`
*/
//: [<< Previous](@previous) - [Index](Index)
import RxSwift
/*:
A Subject is a sort of bridge or proxy that is available in some implementations of ReactiveX that acts both as an observer and as an Observable. Because it is an observer, it can subscribe to one or more Observables, and because it is an Observable, it can pass through the items it observes by reemitting them, and it can also emit new items.
*/
func writeSequenceToConsole<O: ObservableType>(name: String, sequence: O) -> Disposable {
return sequence
.subscribe { e in
print("Subscription: \(name), event: \(e)")
}
}
/*:
## PublishSubject
`PublishSubject` emits to an observer only those items that are emitted by the source Observable(s) subsequent to the time of the subscription.
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/publishsubject.png)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/publishsubject_error.png)
*/
example("PublishSubject") {
let disposeBag = DisposeBag()
let subject = PublishSubject<String>()
writeSequenceToConsole("1", sequence: subject).addDisposableTo(disposeBag)
subject.on(.Next("a"))
subject.on(.Next("b"))
writeSequenceToConsole("2", sequence: subject).addDisposableTo(disposeBag)
subject.on(.Next("c"))
subject.on(.Next("d"))
}
/*:
## ReplaySubject
`ReplaySubject` emits to any observer all of the items that were emitted by the source Observable(s), regardless of when the observer subscribes.
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/replaysubject.png)
*/
example("ReplaySubject") {
let disposeBag = DisposeBag()
let subject = ReplaySubject<String>.create(bufferSize: 1)
writeSequenceToConsole("1", sequence: subject).addDisposableTo(disposeBag)
subject.on(.Next("a"))
subject.on(.Next("b"))
writeSequenceToConsole("2", sequence: subject).addDisposableTo(disposeBag)
subject.on(.Next("c"))
subject.on(.Next("d"))
}
/*:
## BehaviorSubject
When an observer subscribes to a `BehaviorSubject`, it begins by emitting the item most recently emitted by the source Observable (or a seed/default value if none has yet been emitted) and then continues to emit any other items emitted later by the source Observable(s).
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/behaviorsubject.png)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/behaviorsubject_error.png)
*/
example("BehaviorSubject") {
let disposeBag = DisposeBag()
let subject = BehaviorSubject(value: "z")
writeSequenceToConsole("1", sequence: subject).addDisposableTo(disposeBag)
subject.on(.Next("a"))
subject.on(.Next("b"))
writeSequenceToConsole("2", sequence: subject).addDisposableTo(disposeBag)
subject.on(.Next("c"))
subject.on(.Next("d"))
subject.on(.Completed)
}
/*:
## Variable
`Variable` wraps `BehaviorSubject`. Advantage of using variable over `BehaviorSubject` is that variable can never explicitly complete or error out, and `BehaviorSubject` can in case `Error` or `Completed` message is send to it. `Variable` will also automatically complete in case it's being deallocated.
*/
example("Variable") {
let disposeBag = DisposeBag()
let variable = Variable("z")
writeSequenceToConsole("1", sequence: variable.asObservable()).addDisposableTo(disposeBag)
variable.value = "a"
variable.value = "b"
writeSequenceToConsole("2", sequence: variable.asObservable()).addDisposableTo(disposeBag)
variable.value = "c"
variable.value = "d"
}
//: [Index](Index) - [Next >>](@next)

View File

@ -0,0 +1,21 @@
/*:
> # IMPORTANT: To use **Rx.playground**:
1. Open **Rx.xcworkspace**.
1. Build the **RxSwift-OSX** scheme (**Product** **Build**).
1. Open **Rx** playground in the **Project navigator**.
1. Show the Debug Area (**View** **Debug Area** **Show Debug Area**).
----
## Table of Contents:
1. [Introduction](Introduction)
1. [Creating and Subscribing to Observables](Creating_and_Subscribing_to_Observables)
1. [Working with Subjects](Working_with_Subjects)
1. [Combining Operators](Combining_Operators)
1. [Transforming Operators](Transforming_Operators)
1. [Filtering and Conditional Operators](Filtering_and_Conditional_Operators)
1. [Mathematical and Aggregate Operators](Mathematical_and_Aggregate_Operators)
1. [Connectable Operators](Connectable_Operators)
1. [Error Handling Operators](Error_Handling_Operators)
1. [Debugging Operators](Debugging_Operators)
*/
//: [Next](@next)

View File

@ -1,88 +0,0 @@
/*:
> # IMPORTANT: To use `Rx.playground`, please:
1. Open `Rx.xcworkspace`
2. Build `RxSwift-OSX` scheme
3. And then open `Rx` playground in `Rx.xcworkspace` tree view.
4. Choose `View > Show Debug Area`
*/
//: [<< Previous](@previous) - [Index](Index)
import RxSwift
/*:
## Transforming Observables
Operators that transform items that are emitted by an Observable.
*/
/*:
### `map` / `select`
Transform the items emitted by an Observable by applying a function to each item
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/map.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/map.html )
*/
example("map") {
let originalSequence = Observable.of(1, 2, 3)
_ = originalSequence
.map { number in
number * 2
}
.subscribe { print($0) }
}
/*:
### `flatMap`
Transform the items emitted by an Observable into Observables, then flatten the emissions from those into a single Observable
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/flatmap.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/flatmap.html )
*/
example("flatMap") {
let sequenceInt = Observable.of(1, 2, 3)
let sequenceString = Observable.of("A", "B", "C", "D", "E", "F", "--")
_ = sequenceInt
.flatMap { (x:Int) -> Observable<String> in
print("from sequenceInt \(x)")
return sequenceString
}
.subscribe {
print($0)
}
}
/*:
### `scan`
Apply a function to each item emitted by an Observable, sequentially, and emit each successive value
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/scan.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/scan.html )
*/
example("scan") {
let sequenceToSum = Observable.of(0, 1, 2, 3, 4, 5)
_ = sequenceToSum
.scan(0) { acum, elem in
acum + elem
}
.subscribe {
print($0)
}
}
//: [Index](Index) - [Next >>](@next)

View File

@ -0,0 +1,78 @@
/*:
> # IMPORTANT: To use **Rx.playground**:
1. Open **Rx.xcworkspace**.
1. Build the **RxSwift-OSX** scheme (**Product** **Build**).
1. Open **Rx** playground in the **Project navigator**.
1. Show the Debug Area (**View** **Debug Area** **Show Debug Area**).
----
[Previous](@previous) - [Table of Contents](Table_of_Contents)
*/
import RxSwift
/*:
# Transforming Operators
Operators that transform Next event elements emitted by an `Observable` sequence.
## `map`
Applies a transforming closure to elements emitted by an `Observable` sequence, and returns a new `Observable` sequence of the transformed elements. [More info](http://reactivex.io/documentation/operators/map.html)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/map.png)
*/
example("map") {
let disposeBag = DisposeBag()
Observable.of(1, 2, 3)
.map { $0 * $0 }
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}
/*:
----
## `flatMap` and `flatMapLatest`
Transforms the elements emitted by an `Observable` sequence into `Observable` sequences, and merges the emissions from both `Observable` sequences into a single `Observable` sequence. This is also useful when, for example, when you have an `Observable` sequence that itself emits `Observable` sequences, and you want to be able to react to new emissions from either `Observable` sequence. The difference between `flatMap` and `flatMapLatest` is, `flatMapLatest` will only emit elements from the most recent inner `Observable` sequence. [More info](http://reactivex.io/documentation/operators/flatmap.html)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/flatmap.png)
*/
example("flatMap and flatMapLatest") {
let disposeBag = DisposeBag()
struct Player {
var score: Variable<Int>
}
let 👦🏻 = Player(score: Variable(80))
let 👧🏼 = Player(score: Variable(90))
let player = Variable(👦🏻)
player.asObservable()
.flatMap { $0.score.asObservable() } // Change flatMap to flatMapLatest and observe change in printed output
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
👦🏻.score.value = 85
player.value = 👧🏼
👦🏻.score.value = 95 // Will be printed when using flatMap, but will not be printed when using flatMapLatest
👧🏼.score.value = 100
}
/*:
> In this example, using `flatMap` may have unintended consequences. After assigning 👧🏼 to `player.value`, `👧🏼.score` will begin to emit elements, but the previous inner `Observable` sequence (`👦🏻.score`) will also still emit elements. By changing `flatMap` to `flatMapLatest`, only the most recent inner `Observable` sequence (`👧🏼.score`) will emit elements, i.e., setting `👦🏻.score.value` to `95` has no effect.
#
> `flatMapLatest` is actually a combination of the `map` and `switchLatest` operators.
*/
/*:
----
## `scan`
Begins with an initial seed value, and then applies an accumulator closure to each element emitted by an `Observable` sequence, and returns each intermediate result as a single-element `Observable` sequence. [More info](http://reactivex.io/documentation/operators/scan.html)
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/scan.png)
*/
example("scan") {
let disposeBag = DisposeBag()
Observable.of(10, 100, 1000)
.scan(1) { aggregateValue, newValue in
aggregateValue + newValue
}
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}
//: [Next](@next) - [Table of Contents](Table_of_Contents)

View File

@ -0,0 +1,110 @@
/*:
> # IMPORTANT: To use **Rx.playground**:
1. Open **Rx.xcworkspace**.
1. Build the **RxSwift-OSX** scheme (**Product** **Build**).
1. Open **Rx** playground in the **Project navigator**.
1. Show the Debug Area (**View** **Debug Area** **Show Debug Area**).
----
[Previous](@previous) - [Table of Contents](Table_of_Contents)
*/
import RxSwift
/*:
# Working with Subjects
A Subject is a sort of bridge or proxy that is available in some implementations of Rx that acts as both an observer and `Observable`. Because it is an observer, it can subscribe to one or more `Observable`s, and because it is an `Observable`, it can pass through the items it observes by reemitting them, and it can also emit new items. [More info](http://reactivex.io/documentation/subject.html)
*/
extension ObservableType {
/**
Add observer with `id` and print each emitted event.
- parameter id: an identifier for the subscription.
*/
func addObserver(_ id: String) -> Disposable {
return subscribe { print("Subscription:", id, "Event:", $0) }
}
}
func writeSequenceToConsole<O: ObservableType>(name: String, sequence: O) -> Disposable {
return sequence.subscribe { event in
print("Subscription: \(name), event: \(event)")
}
}
/*:
## PublishSubject
Broadcasts new events to all observers as of their time of the subscription.
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/publishsubject.png "PublishSubject")
*/
example("PublishSubject") {
let disposeBag = DisposeBag()
let subject = PublishSubject<String>()
subject.addObserver("1").addDisposableTo(disposeBag)
subject.onNext("🐶")
subject.onNext("🐱")
subject.addObserver("2").addDisposableTo(disposeBag)
subject.onNext("🅰️")
subject.onNext("🅱️")
}
/*:
> This example also introduces using the `onNext(_:)` convenience method, equivalent to `on(.next(_:)`, which causes a new Next event to be emitted to subscribers with the provided `element`. There are also `onError(_:)` and `onCompleted()` convenience methods, equivalent to `on(.error(_:))` and `on(.completed)`, respectively.
----
## ReplaySubject
Broadcasts new events to all subscribers, and the specified `bufferSize` number of previous events to new subscribers.
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/replaysubject.png)
*/
example("ReplaySubject") {
let disposeBag = DisposeBag()
let subject = ReplaySubject<String>.create(bufferSize: 1)
subject.addObserver("1").addDisposableTo(disposeBag)
subject.onNext("🐶")
subject.onNext("🐱")
subject.addObserver("2").addDisposableTo(disposeBag)
subject.onNext("🅰️")
subject.onNext("🅱️")
}
/*:
----
## BehaviorSubject
Broadcasts new events to all subscribers, and the most recent (or initial) value to new subscribers.
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/behaviorsubject.png)
*/
example("BehaviorSubject") {
let disposeBag = DisposeBag()
let subject = BehaviorSubject(value: "🔴")
subject.addObserver("1").addDisposableTo(disposeBag)
subject.onNext("🐶")
subject.onNext("🐱")
subject.addObserver("2").addDisposableTo(disposeBag)
subject.onNext("🅰️")
subject.onNext("🅱️")
subject.addObserver("3").addDisposableTo(disposeBag)
subject.onNext("🍐")
subject.onNext("🍊")
}
/*:
> Notice what's missing in these previous examples? A Completed event. `PublishSubject`, `ReplaySubject`, and `BehaviorSubject` do not automatically emit Completed events when they are about to be disposed of.
----
## Variable
Wraps a `BehaviorSubject`, so it will emit the most recent (or initial) value to new subscribers. And `Variable` also maintains current value state. `Variable` will never emit an Error event. However, it will automatically emit a Completed event and terminate on `deinit`.
*/
example("Variable") {
let disposeBag = DisposeBag()
let variable = Variable("🔴")
variable.asObservable().addObserver("1").addDisposableTo(disposeBag)
variable.value = "🐶"
variable.value = "🐱"
variable.asObservable().addObserver("2").addDisposableTo(disposeBag)
variable.value = "🅰️"
variable.value = "🅱️"
}
//: > Call `asObservable()` on a `Variable` instance in order to access its underlying `BehaviorSubject` sequence. `Variable`s do not implement the `on` operator (or, e.g., `onNext(_:)`), but instead expose a `value` property that can be used to get the current value, and also set a new value. Setting a new value will also add that value onto its underlying `BehaviorSubject` sequence.
//: [Next](@next) - [Table of Contents](Table_of_Contents)

View File

@ -1,31 +1,47 @@
import Foundation
public func example(description: String, action: () -> ()) {
print("\n--- \(description) example ---")
/**
Encloses each code example in its own scope. Prints a `description` header and then executes the `action` closure.
- parameter description: example description
- parameter action: `Void` closure
*/
public func example(_ description: String, action: (Void) -> Void) {
printExampleHeader(description)
action()
}
public func delay(delay:Double, closure:()->()) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(delay * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(), closure)
public func printExampleHeader(_ description: String) {
print("\n--- \(description) example ---")
}
public enum TestError: Swift.Error {
case test
}
/**
Executes `closure` on main thread after `delay` seconds.
- parameter delay: time in seconds to wait before executing `closure`
- parameter closure: `Void` closure
*/
public func delay(_ delay: Double, closure: @escaping (Void) -> Void) {
let delayTime = DispatchTime.now() + DispatchTimeInterval.seconds(Int(delay))
DispatchQueue.main.asyncAfter(deadline: delayTime) {
closure()
}
}
#if NOT_IN_PLAYGROUND
public func playgroundShouldContinueIndefinitely() {
}
public func playgroundShouldContinueIndefinitely() { }
#else
import XCPlayground
public func playgroundShouldContinueIndefinitely() {
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
}
import PlaygroundSupport
public func playgroundShouldContinueIndefinitely() {
PlaygroundPage.current.needsIndefiniteExecution = true
}
#endif

View File

@ -0,0 +1,12 @@
[
{
"file": "/Users/mo/Documents/OpenSource/RxSwift/Rx.playground/Sources/SupportCode.swift",
"offset": 276,
"remove": 9,
},
{
"file": "/Users/mo/Documents/OpenSource/RxSwift/Rx.playground/Sources/SupportCode.swift",
"offset": 733,
"text": "@escaping ",
}
]

View File

@ -1,16 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='6.0' target-platform='osx' display-mode='raw'>
<playground version='6.0' target-platform='osx' display-mode='raw' last-migration='0800'>
<pages>
<page name='Index'/>
<page name='Table_of_Contents'/>
<page name='Introduction'/>
<page name='Subjects'/>
<page name='Transforming_Observables'/>
<page name='Filtering_Observables'/>
<page name='Combining_Observables'/>
<page name='Error_Handling_Operators'/>
<page name='Observable_Utility_Operators'/>
<page name='Conditional_and_Boolean_Operators'/>
<page name='Creating_and_Subscribing_to_Observables'/>
<page name='Working_with_Subjects'/>
<page name='Combining_Operators'/>
<page name='Transforming_Operators'/>
<page name='Filtering_and_Conditional_Operators'/>
<page name='Mathematical_and_Aggregate_Operators'/>
<page name='Connectable_Observable_Operators'/>
<page name='Connectable_Operators'/>
<page name='Error_Handling_Operators'/>
<page name='Debugging_Operators'/>
<page name='Enable_RxSwift.resourceCount'/>
</pages>
</playground>

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0720"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0720"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0720"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0720"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0720"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0720"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0720"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0720"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0720"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0720"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0720"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0720"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0720"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0720"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0720"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -1,6 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Rx.playground">
</FileRef>
<FileRef
location = "group:Package.swift">
</FileRef>
@ -10,6 +13,9 @@
<FileRef
location = "group:README.md">
</FileRef>
<FileRef
location = "group:ISSUE_TEMPLATE.md">
</FileRef>
<FileRef
location = "group:CHANGELOG.md">
</FileRef>
@ -32,33 +38,8 @@
<Group
location = "group:scripts"
name = "scripts">
<Group
location = "group:automation-tests"
name = "automation-tests">
<FileRef
location = "group:01_githubSignUp.js">
</FileRef>
<FileRef
location = "group:02_searchWikipedia.js">
</FileRef>
<FileRef
location = "group:03_masterDetail.js">
</FileRef>
<FileRef
location = "group:04_controlsTests.js">
</FileRef>
<FileRef
location = "group:05_reactivePartialUpdates.js">
</FileRef>
<FileRef
location = "group:common.js">
</FileRef>
<FileRef
location = "group:main.js">
</FileRef>
</Group>
<FileRef
location = "group:automation-tests.sh">
location = "group:all-tests.sh">
</FileRef>
<FileRef
location = "group:common.sh">
@ -66,9 +47,6 @@
<FileRef
location = "group:/Users/kzaher/Projects/RxSwift/scripts/package-spm.swift">
</FileRef>
<FileRef
location = "group:pre-release-tests.sh">
</FileRef>
<FileRef
location = "group:test-linux.sh">
</FileRef>
@ -103,9 +81,6 @@
<FileRef
location = "group:HotAndColdObservables.md">
</FileRef>
<FileRef
location = "group:IssueTemplate.md">
</FileRef>
<FileRef
location = "group:Linux.md">
</FileRef>
@ -128,9 +103,6 @@
location = "group:Warnings.md">
</FileRef>
</Group>
<FileRef
location = "group:Rx.playground">
</FileRef>
<FileRef
location = "group:Rx.xcodeproj">
</FileRef>

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "RxBlocking"
s.version = "2.3.1"
s.version = "3.0.0.alpha.1"
s.summary = "RxSwift Blocking operatos"
s.description = <<-DESC
Set of blocking operators for RxSwift. These operators are mostly intended for unit/integration tests
@ -18,11 +18,11 @@ Waiting for observable sequence to complete before exiting command line applicat
s.requires_arc = true
s.ios.deployment_target = '8.0'
s.osx.deployment_target = '10.9'
s.osx.deployment_target = '10.10'
s.watchos.deployment_target = '2.0'
s.tvos.deployment_target = '9.0'
s.source_files = 'RxBlocking/**/*.swift'
s.dependency 'RxSwift', '~> 2.3.1'
s.dependency 'RxSwift', '~> 3.0.0.alpha.1'
end

View File

@ -22,7 +22,7 @@ extension BlockingObservable {
public func toArray() throws -> [E] {
var elements: [E] = Array<E>()
var error: ErrorType?
var error: Swift.Error?
let lock = RunLoopLock()
@ -30,17 +30,17 @@ extension BlockingObservable {
lock.dispatch {
d.disposable = self.source.subscribe { e in
if d.disposed {
if d.isDisposed {
return
}
switch e {
case .Next(let element):
case .next(let element):
elements.append(element)
case .Error(let e):
case .error(let e):
error = e
d.dispose()
lock.stop()
case .Completed:
case .completed:
d.dispose()
lock.stop()
}
@ -70,7 +70,7 @@ extension BlockingObservable {
public func first() throws -> E? {
var element: E?
var error: ErrorType?
var error: Swift.Error?
let d = SingleAssignmentDisposable()
@ -78,17 +78,17 @@ extension BlockingObservable {
lock.dispatch {
d.disposable = self.source.subscribe { e in
if d.disposed {
if d.isDisposed {
return
}
switch e {
case .Next(let e):
case .next(let e):
if element == nil {
element = e
}
break
case .Error(let e):
case .error(let e):
error = e
default:
break
@ -122,7 +122,7 @@ extension BlockingObservable {
public func last() throws -> E? {
var element: E?
var error: ErrorType?
var error: Swift.Error?
let d = SingleAssignmentDisposable()
@ -130,14 +130,14 @@ extension BlockingObservable {
lock.dispatch {
d.disposable = self.source.subscribe { e in
if d.disposed {
if d.isDisposed {
return
}
switch e {
case .Next(let e):
case .next(let e):
element = e
return
case .Error(let e):
case .error(let e):
error = e
default:
break
@ -180,10 +180,10 @@ extension BlockingObservable {
- parameter predicate: A function to test each source element for a condition.
- returns: Returns the only element of an sequence that satisfies the condition in the predicate, and reports an error if there is not exactly one element in the sequence.
*/
public func single(predicate: (E) throws -> Bool) throws -> E? {
public func single(_ predicate: @escaping (E) throws -> Bool) throws -> E? {
var element: E?
var error: ErrorType?
var error: Swift.Error?
let d = SingleAssignmentDisposable()
@ -191,11 +191,11 @@ extension BlockingObservable {
lock.dispatch {
d.disposable = self.source.subscribe { e in
if d.disposed {
if d.isDisposed {
return
}
switch e {
case .Next(let e):
case .next(let e):
do {
if try !predicate(e) {
return
@ -203,7 +203,7 @@ extension BlockingObservable {
if element == nil {
element = e
} else {
throw RxError.MoreThanOneElement
throw RxError.moreThanOneElement
}
} catch (let err) {
error = err
@ -211,11 +211,11 @@ extension BlockingObservable {
lock.stop()
}
return
case .Error(let e):
case .error(let e):
error = e
case .Completed:
case .completed:
if element == nil {
error = RxError.NoElements
error = RxError.noElements
}
}

Binary file not shown.

View File

@ -17,8 +17,8 @@ extension ObservableConvertibleType {
- returns: `BlockingObservable` version of `self`
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func toBlocking() -> BlockingObservable<E> {
return BlockingObservable(source: self.asObservable())
}
}
}

View File

@ -29,7 +29,7 @@ typealias AtomicInt = Int32
#endif
class RunLoopLock {
let currentRunLoop: CFRunLoopRef
let currentRunLoop: CFRunLoop
var calledRun: AtomicInt = 0
var calledStop: AtomicInt = 0
@ -38,12 +38,12 @@ class RunLoopLock {
currentRunLoop = CFRunLoopGetCurrent()
}
func dispatch(action: () -> ()) {
CFRunLoopPerformBlock(currentRunLoop, kCFRunLoopDefaultMode) {
func dispatch(_ action: @escaping () -> ()) {
CFRunLoopPerformBlock(currentRunLoop, CFRunLoopMode.defaultMode.rawValue) {
if CurrentThreadScheduler.isScheduleRequired {
CurrentThreadScheduler.instance.schedule(()) { _ in
_ = CurrentThreadScheduler.instance.schedule(()) { _ in
action()
return NopDisposable.instance
return Disposables.create()
}
}
else {
@ -57,7 +57,7 @@ class RunLoopLock {
if AtomicIncrement(&calledStop) != 1 {
return
}
CFRunLoopPerformBlock(currentRunLoop, kCFRunLoopDefaultMode) {
CFRunLoopPerformBlock(currentRunLoop, CFRunLoopMode.defaultMode.rawValue) {
CFRunLoopStop(self.currentRunLoop)
}
CFRunLoopWakeUp(currentRunLoop)

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "RxCocoa"
s.version = "2.3.1"
s.version = "3.0.0.alpha.1"
s.summary = "RxSwift Cocoa extensions"
s.description = <<-DESC
* UI extensions
@ -15,7 +15,7 @@ Pod::Spec.new do |s|
s.requires_arc = true
s.ios.deployment_target = '8.0'
s.osx.deployment_target = '10.9'
s.osx.deployment_target = '10.10'
s.watchos.deployment_target = '2.0'
s.tvos.deployment_target = '9.0'
@ -25,5 +25,5 @@ Pod::Spec.new do |s|
s.watchos.source_files = 'RxCocoa/iOS/**/*.swift'
s.tvos.source_files = 'RxCocoa/iOS/**/*.swift'
s.dependency 'RxSwift', '~> 2.3.1'
s.dependency 'RxSwift', '~> 3.0.0.alpha.1'
end

View File

@ -12,15 +12,15 @@ import RxSwift
#endif
extension CLLocationManager {
extension Reactive where Base: CLLocationManager {
/**
Reactive wrapper for `delegate`.
For more information take a look at `DelegateProxyType` protocol documentation.
*/
public var rx_delegate: DelegateProxy {
return proxyForObject(RxCLLocationManagerDelegateProxy.self, self)
public var delegate: DelegateProxy {
return RxCLLocationManagerDelegateProxy.proxyForObject(base)
}
// MARK: Responding to Location Events
@ -28,8 +28,8 @@ extension CLLocationManager {
/**
Reactive wrapper for `delegate` message.
*/
public var rx_didUpdateLocations: Observable<[CLLocation]> {
return rx_delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:didUpdateLocations:)))
public var didUpdateLocations: Observable<[CLLocation]> {
return delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:didUpdateLocations:)))
.map { a in
return try castOrThrow([CLLocation].self, a[1])
}
@ -38,8 +38,8 @@ extension CLLocationManager {
/**
Reactive wrapper for `delegate` message.
*/
public var rx_didFailWithError: Observable<NSError> {
return rx_delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:didFailWithError:)))
public var didFailWithError: Observable<NSError> {
return delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:didFailWithError:)))
.map { a in
return try castOrThrow(NSError.self, a[1])
}
@ -49,8 +49,8 @@ extension CLLocationManager {
/**
Reactive wrapper for `delegate` message.
*/
public var rx_didFinishDeferredUpdatesWithError: Observable<NSError?> {
return rx_delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:didFinishDeferredUpdatesWithError:)))
public var didFinishDeferredUpdatesWithError: Observable<NSError?> {
return delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:didFinishDeferredUpdatesWithError:)))
.map { a in
return try castOptionalOrThrow(NSError.self, a[1])
}
@ -64,8 +64,8 @@ extension CLLocationManager {
/**
Reactive wrapper for `delegate` message.
*/
public var rx_didPauseLocationUpdates: Observable<Void> {
return rx_delegate.observe(#selector(CLLocationManagerDelegate.locationManagerDidPauseLocationUpdates(_:)))
public var didPauseLocationUpdates: Observable<Void> {
return delegate.observe(#selector(CLLocationManagerDelegate.locationManagerDidPauseLocationUpdates(_:)))
.map { _ in
return ()
}
@ -74,8 +74,8 @@ extension CLLocationManager {
/**
Reactive wrapper for `delegate` message.
*/
public var rx_didResumeLocationUpdates: Observable<Void> {
return rx_delegate.observe(#selector(CLLocationManagerDelegate.locationManagerDidResumeLocationUpdates(_:)))
public var didResumeLocationUpdates: Observable<Void> {
return delegate.observe( #selector(CLLocationManagerDelegate.locationManagerDidResumeLocationUpdates(_:)))
.map { _ in
return ()
}
@ -86,8 +86,8 @@ extension CLLocationManager {
/**
Reactive wrapper for `delegate` message.
*/
public var rx_didUpdateHeading: Observable<CLHeading> {
return rx_delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:didUpdateHeading:)))
public var didUpdateHeading: Observable<CLHeading> {
return delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:didUpdateHeading:)))
.map { a in
return try castOrThrow(CLHeading.self, a[1])
}
@ -98,8 +98,8 @@ extension CLLocationManager {
/**
Reactive wrapper for `delegate` message.
*/
public var rx_didEnterRegion: Observable<CLRegion> {
return rx_delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:didEnterRegion:)))
public var didEnterRegion: Observable<CLRegion> {
return delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:didEnterRegion:)))
.map { a in
return try castOrThrow(CLRegion.self, a[1])
}
@ -108,8 +108,8 @@ extension CLLocationManager {
/**
Reactive wrapper for `delegate` message.
*/
public var rx_didExitRegion: Observable<CLRegion> {
return rx_delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:didExitRegion:)))
public var didExitRegion: Observable<CLRegion> {
return delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:didExitRegion:)))
.map { a in
return try castOrThrow(CLRegion.self, a[1])
}
@ -123,11 +123,11 @@ extension CLLocationManager {
Reactive wrapper for `delegate` message.
*/
@available(OSX 10.10, *)
public var rx_didDetermineStateForRegion: Observable<(state: CLRegionState, region: CLRegion)> {
return rx_delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:didDetermineState:forRegion:)))
public var didDetermineStateForRegion: Observable<(state: CLRegionState, region: CLRegion)> {
return delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:didDetermineState:for:)))
.map { a in
let stateNumber = try castOrThrow(NSNumber.self, a[1])
let state = CLRegionState(rawValue: stateNumber.integerValue) ?? CLRegionState.Unknown
let state = CLRegionState(rawValue: stateNumber.intValue) ?? CLRegionState.unknown
let region = try castOrThrow(CLRegion.self, a[2])
return (state: state, region: region)
}
@ -136,8 +136,8 @@ extension CLLocationManager {
/**
Reactive wrapper for `delegate` message.
*/
public var rx_monitoringDidFailForRegionWithError: Observable<(region: CLRegion?, error: NSError)> {
return rx_delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:monitoringDidFailForRegion:withError:)))
public var monitoringDidFailForRegionWithError: Observable<(region: CLRegion?, error: NSError)> {
return delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:monitoringDidFailFor:withError:)))
.map { a in
let region = try castOptionalOrThrow(CLRegion.self, a[1])
let error = try castOrThrow(NSError.self, a[2])
@ -148,8 +148,8 @@ extension CLLocationManager {
/**
Reactive wrapper for `delegate` message.
*/
public var rx_didStartMonitoringForRegion: Observable<CLRegion> {
return rx_delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:didStartMonitoringForRegion:)))
public var didStartMonitoringForRegion: Observable<CLRegion> {
return delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:didStartMonitoringFor:)))
.map { a in
return try castOrThrow(CLRegion.self, a[1])
}
@ -164,8 +164,8 @@ extension CLLocationManager {
/**
Reactive wrapper for `delegate` message.
*/
public var rx_didRangeBeaconsInRegion: Observable<(beacons: [CLBeacon], region: CLBeaconRegion)> {
return rx_delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:didRangeBeacons:inRegion:)))
public var didRangeBeaconsInRegion: Observable<(beacons: [CLBeacon], region: CLBeaconRegion)> {
return delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:didRangeBeacons:in:)))
.map { a in
let beacons = try castOrThrow([CLBeacon].self, a[1])
let region = try castOrThrow(CLBeaconRegion.self, a[2])
@ -176,8 +176,8 @@ extension CLLocationManager {
/**
Reactive wrapper for `delegate` message.
*/
public var rx_rangingBeaconsDidFailForRegionWithError: Observable<(region: CLBeaconRegion, error: NSError)> {
return rx_delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:rangingBeaconsDidFailForRegion:withError:)))
public var rangingBeaconsDidFailForRegionWithError: Observable<(region: CLBeaconRegion, error: NSError)> {
return delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:rangingBeaconsDidFailFor:withError:)))
.map { a in
let region = try castOrThrow(CLBeaconRegion.self, a[1])
let error = try castOrThrow(NSError.self, a[2])
@ -191,8 +191,8 @@ extension CLLocationManager {
Reactive wrapper for `delegate` message.
*/
@available(iOS 8.0, *)
public var rx_didVisit: Observable<CLVisit> {
return rx_delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:didVisit:)))
public var didVisit: Observable<CLVisit> {
return delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:didVisit:)))
.map { a in
return try castOrThrow(CLVisit.self, a[1])
}
@ -205,11 +205,11 @@ extension CLLocationManager {
/**
Reactive wrapper for `delegate` message.
*/
public var rx_didChangeAuthorizationStatus: Observable<CLAuthorizationStatus> {
return rx_delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:didChangeAuthorizationStatus:)))
public var didChangeAuthorizationStatus: Observable<CLAuthorizationStatus> {
return delegate.observe(#selector(CLLocationManagerDelegate.locationManager(_:didChangeAuthorization:)))
.map { a in
let number = try castOrThrow(NSNumber.self, a[1])
return CLAuthorizationStatus(rawValue: Int32(number.integerValue)) ?? .NotDetermined
return CLAuthorizationStatus(rawValue: Int32(number.intValue)) ?? .notDetermined
}
}

View File

@ -54,7 +54,7 @@ public struct ControlEvent<PropertyType> : ControlEventType {
- parameter events: Observable sequence that represents events.
- returns: Control event created with a observable sequence of events.
*/
public init<Ev: ObservableType where Ev.E == E>(events: Ev) {
public init<Ev: ObservableType>(events: Ev) where Ev.E == E {
_events = events.subscribeOn(ConcurrentMainScheduler.instance)
}
@ -64,14 +64,14 @@ public struct ControlEvent<PropertyType> : ControlEventType {
- parameter observer: Observer to subscribe to events.
- returns: Disposable object that can be used to unsubscribe the observer from receiving control events.
*/
public func subscribe<O : ObserverType where O.E == E>(observer: O) -> Disposable {
public func subscribe<O : ObserverType>(_ observer: O) -> Disposable where O.E == E {
return _events.subscribe(observer)
}
/**
- returns: `Observable` interface.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func asObservable() -> Observable<E> {
return _events
}
@ -79,7 +79,7 @@ public struct ControlEvent<PropertyType> : ControlEventType {
/**
- returns: `ControlEvent` interface.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func asControlEvent() -> ControlEvent<E> {
return self
}

View File

@ -59,7 +59,7 @@ public struct ControlProperty<PropertyType> : ControlPropertyType {
- returns: Control property created with a observable sequence of values and an observer that enables binding values
to property.
*/
public init<V: ObservableType, S: ObserverType where E == V.E, E == S.E>(values: V, valueSink: S) {
public init<V: ObservableType, S: ObserverType>(values: V, valueSink: S) where E == V.E, E == S.E {
_values = values.subscribeOn(ConcurrentMainScheduler.instance)
_valueSink = valueSink.asObserver()
}
@ -70,14 +70,14 @@ public struct ControlProperty<PropertyType> : ControlPropertyType {
- parameter observer: Observer to subscribe to property values.
- returns: Disposable object that can be used to unsubscribe the observer from receiving control property values.
*/
public func subscribe<O : ObserverType where O.E == E>(observer: O) -> Disposable {
public func subscribe<O : ObserverType>(_ observer: O) -> Disposable where O.E == E {
return _values.subscribe(observer)
}
/**
- returns: `Observable` interface.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func asObservable() -> Observable<E> {
return _values
}
@ -85,7 +85,7 @@ public struct ControlProperty<PropertyType> : ControlPropertyType {
/**
- returns: `ControlProperty` interface.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func asControlProperty() -> ControlProperty<E> {
return self
}
@ -97,13 +97,13 @@ public struct ControlProperty<PropertyType> : ControlPropertyType {
- In case error is received, DEBUG buids raise fatal error, RELEASE builds log event to standard output.
- In case sequence completes, nothing happens.
*/
public func on(event: Event<E>) {
public func on(_ event: Event<E>) {
switch event {
case .Error(let error):
case .error(let error):
bindingErrorToInterface(error)
case .Next:
case .next:
_valueSink.on(event)
case .Completed:
case .completed:
_valueSink.on(event)
}
}

View File

@ -17,7 +17,7 @@ extension ControlEvent {
`ControlEvent` already can't fail, so no special case needs to be handled.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func asDriver() -> Driver<E> {
return self.asDriver { (error) -> Driver<E> in
#if DEBUG
@ -27,4 +27,4 @@ extension ControlEvent {
#endif
}
}
}
}

View File

@ -17,7 +17,7 @@ extension ControlProperty {
`ControlProperty` already can't fail, so no special case needs to be handled.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func asDriver() -> Driver<E> {
return self.asDriver { (error) -> Driver<E> in
#if DEBUG
@ -27,4 +27,4 @@ extension ControlProperty {
#endif
}
}
}
}

View File

@ -23,9 +23,9 @@ extension Driver {
- parameter resultSelector: Function to invoke for each series of elements at corresponding indexes in the sources.
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public static func zip<O1: DriverConvertibleType, O2: DriverConvertibleType>
(source1: O1, _ source2: O2, resultSelector: (O1.E, O2.E) throws -> E)
(_ source1: O1, _ source2: O2, resultSelector: @escaping (O1.E, O2.E) throws -> E)
-> Driver<E> {
let source = Observable.zip(
source1.asDriver().asObservable(), source2.asDriver().asObservable(),
@ -43,9 +43,9 @@ extension Driver {
- parameter resultSelector: Function to invoke whenever any of the sources produces an element.
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public static func combineLatest<O1: DriverConvertibleType, O2: DriverConvertibleType>
(source1: O1, _ source2: O2, resultSelector: (O1.E, O2.E) throws -> E)
(_ source1: O1, _ source2: O2, resultSelector: @escaping (O1.E, O2.E) throws -> E)
-> Driver<E> {
let source = Observable.combineLatest(
source1.asDriver().asObservable(), source2.asDriver().asObservable(),
@ -67,9 +67,9 @@ extension Driver {
- parameter resultSelector: Function to invoke for each series of elements at corresponding indexes in the sources.
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public static func zip<O1: DriverConvertibleType, O2: DriverConvertibleType, O3: DriverConvertibleType>
(source1: O1, _ source2: O2, _ source3: O3, resultSelector: (O1.E, O2.E, O3.E) throws -> E)
(_ source1: O1, _ source2: O2, _ source3: O3, resultSelector: @escaping (O1.E, O2.E, O3.E) throws -> E)
-> Driver<E> {
let source = Observable.zip(
source1.asDriver().asObservable(), source2.asDriver().asObservable(), source3.asDriver().asObservable(),
@ -87,9 +87,9 @@ extension Driver {
- parameter resultSelector: Function to invoke whenever any of the sources produces an element.
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public static func combineLatest<O1: DriverConvertibleType, O2: DriverConvertibleType, O3: DriverConvertibleType>
(source1: O1, _ source2: O2, _ source3: O3, resultSelector: (O1.E, O2.E, O3.E) throws -> E)
(_ source1: O1, _ source2: O2, _ source3: O3, resultSelector: @escaping (O1.E, O2.E, O3.E) throws -> E)
-> Driver<E> {
let source = Observable.combineLatest(
source1.asDriver().asObservable(), source2.asDriver().asObservable(), source3.asDriver().asObservable(),
@ -111,9 +111,9 @@ extension Driver {
- parameter resultSelector: Function to invoke for each series of elements at corresponding indexes in the sources.
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public static func zip<O1: DriverConvertibleType, O2: DriverConvertibleType, O3: DriverConvertibleType, O4: DriverConvertibleType>
(source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, resultSelector: (O1.E, O2.E, O3.E, O4.E) throws -> E)
(_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, resultSelector: @escaping (O1.E, O2.E, O3.E, O4.E) throws -> E)
-> Driver<E> {
let source = Observable.zip(
source1.asDriver().asObservable(), source2.asDriver().asObservable(), source3.asDriver().asObservable(), source4.asDriver().asObservable(),
@ -131,9 +131,9 @@ extension Driver {
- parameter resultSelector: Function to invoke whenever any of the sources produces an element.
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public static func combineLatest<O1: DriverConvertibleType, O2: DriverConvertibleType, O3: DriverConvertibleType, O4: DriverConvertibleType>
(source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, resultSelector: (O1.E, O2.E, O3.E, O4.E) throws -> E)
(_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, resultSelector: @escaping (O1.E, O2.E, O3.E, O4.E) throws -> E)
-> Driver<E> {
let source = Observable.combineLatest(
source1.asDriver().asObservable(), source2.asDriver().asObservable(), source3.asDriver().asObservable(), source4.asDriver().asObservable(),
@ -155,9 +155,9 @@ extension Driver {
- parameter resultSelector: Function to invoke for each series of elements at corresponding indexes in the sources.
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public static func zip<O1: DriverConvertibleType, O2: DriverConvertibleType, O3: DriverConvertibleType, O4: DriverConvertibleType, O5: DriverConvertibleType>
(source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, resultSelector: (O1.E, O2.E, O3.E, O4.E, O5.E) throws -> E)
(_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, resultSelector: @escaping (O1.E, O2.E, O3.E, O4.E, O5.E) throws -> E)
-> Driver<E> {
let source = Observable.zip(
source1.asDriver().asObservable(), source2.asDriver().asObservable(), source3.asDriver().asObservable(), source4.asDriver().asObservable(), source5.asDriver().asObservable(),
@ -175,9 +175,9 @@ extension Driver {
- parameter resultSelector: Function to invoke whenever any of the sources produces an element.
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public static func combineLatest<O1: DriverConvertibleType, O2: DriverConvertibleType, O3: DriverConvertibleType, O4: DriverConvertibleType, O5: DriverConvertibleType>
(source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, resultSelector: (O1.E, O2.E, O3.E, O4.E, O5.E) throws -> E)
(_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, resultSelector: @escaping (O1.E, O2.E, O3.E, O4.E, O5.E) throws -> E)
-> Driver<E> {
let source = Observable.combineLatest(
source1.asDriver().asObservable(), source2.asDriver().asObservable(), source3.asDriver().asObservable(), source4.asDriver().asObservable(), source5.asDriver().asObservable(),
@ -199,9 +199,9 @@ extension Driver {
- parameter resultSelector: Function to invoke for each series of elements at corresponding indexes in the sources.
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public static func zip<O1: DriverConvertibleType, O2: DriverConvertibleType, O3: DriverConvertibleType, O4: DriverConvertibleType, O5: DriverConvertibleType, O6: DriverConvertibleType>
(source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, resultSelector: (O1.E, O2.E, O3.E, O4.E, O5.E, O6.E) throws -> E)
(_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, resultSelector: @escaping (O1.E, O2.E, O3.E, O4.E, O5.E, O6.E) throws -> E)
-> Driver<E> {
let source = Observable.zip(
source1.asDriver().asObservable(), source2.asDriver().asObservable(), source3.asDriver().asObservable(), source4.asDriver().asObservable(), source5.asDriver().asObservable(), source6.asDriver().asObservable(),
@ -219,9 +219,9 @@ extension Driver {
- parameter resultSelector: Function to invoke whenever any of the sources produces an element.
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public static func combineLatest<O1: DriverConvertibleType, O2: DriverConvertibleType, O3: DriverConvertibleType, O4: DriverConvertibleType, O5: DriverConvertibleType, O6: DriverConvertibleType>
(source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, resultSelector: (O1.E, O2.E, O3.E, O4.E, O5.E, O6.E) throws -> E)
(_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, resultSelector: @escaping (O1.E, O2.E, O3.E, O4.E, O5.E, O6.E) throws -> E)
-> Driver<E> {
let source = Observable.combineLatest(
source1.asDriver().asObservable(), source2.asDriver().asObservable(), source3.asDriver().asObservable(), source4.asDriver().asObservable(), source5.asDriver().asObservable(), source6.asDriver().asObservable(),
@ -243,9 +243,9 @@ extension Driver {
- parameter resultSelector: Function to invoke for each series of elements at corresponding indexes in the sources.
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public static func zip<O1: DriverConvertibleType, O2: DriverConvertibleType, O3: DriverConvertibleType, O4: DriverConvertibleType, O5: DriverConvertibleType, O6: DriverConvertibleType, O7: DriverConvertibleType>
(source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, _ source7: O7, resultSelector: (O1.E, O2.E, O3.E, O4.E, O5.E, O6.E, O7.E) throws -> E)
(_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, _ source7: O7, resultSelector: @escaping (O1.E, O2.E, O3.E, O4.E, O5.E, O6.E, O7.E) throws -> E)
-> Driver<E> {
let source = Observable.zip(
source1.asDriver().asObservable(), source2.asDriver().asObservable(), source3.asDriver().asObservable(), source4.asDriver().asObservable(), source5.asDriver().asObservable(), source6.asDriver().asObservable(), source7.asDriver().asObservable(),
@ -263,9 +263,9 @@ extension Driver {
- parameter resultSelector: Function to invoke whenever any of the sources produces an element.
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public static func combineLatest<O1: DriverConvertibleType, O2: DriverConvertibleType, O3: DriverConvertibleType, O4: DriverConvertibleType, O5: DriverConvertibleType, O6: DriverConvertibleType, O7: DriverConvertibleType>
(source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, _ source7: O7, resultSelector: (O1.E, O2.E, O3.E, O4.E, O5.E, O6.E, O7.E) throws -> E)
(_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, _ source7: O7, resultSelector: @escaping (O1.E, O2.E, O3.E, O4.E, O5.E, O6.E, O7.E) throws -> E)
-> Driver<E> {
let source = Observable.combineLatest(
source1.asDriver().asObservable(), source2.asDriver().asObservable(), source3.asDriver().asObservable(), source4.asDriver().asObservable(), source5.asDriver().asObservable(), source6.asDriver().asObservable(), source7.asDriver().asObservable(),
@ -287,9 +287,9 @@ extension Driver {
- parameter resultSelector: Function to invoke for each series of elements at corresponding indexes in the sources.
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public static func zip<O1: DriverConvertibleType, O2: DriverConvertibleType, O3: DriverConvertibleType, O4: DriverConvertibleType, O5: DriverConvertibleType, O6: DriverConvertibleType, O7: DriverConvertibleType, O8: DriverConvertibleType>
(source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, _ source7: O7, _ source8: O8, resultSelector: (O1.E, O2.E, O3.E, O4.E, O5.E, O6.E, O7.E, O8.E) throws -> E)
(_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, _ source7: O7, _ source8: O8, resultSelector: @escaping (O1.E, O2.E, O3.E, O4.E, O5.E, O6.E, O7.E, O8.E) throws -> E)
-> Driver<E> {
let source = Observable.zip(
source1.asDriver().asObservable(), source2.asDriver().asObservable(), source3.asDriver().asObservable(), source4.asDriver().asObservable(), source5.asDriver().asObservable(), source6.asDriver().asObservable(), source7.asDriver().asObservable(), source8.asDriver().asObservable(),
@ -307,9 +307,9 @@ extension Driver {
- parameter resultSelector: Function to invoke whenever any of the sources produces an element.
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public static func combineLatest<O1: DriverConvertibleType, O2: DriverConvertibleType, O3: DriverConvertibleType, O4: DriverConvertibleType, O5: DriverConvertibleType, O6: DriverConvertibleType, O7: DriverConvertibleType, O8: DriverConvertibleType>
(source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, _ source7: O7, _ source8: O8, resultSelector: (O1.E, O2.E, O3.E, O4.E, O5.E, O6.E, O7.E, O8.E) throws -> E)
(_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, _ source7: O7, _ source8: O8, resultSelector: @escaping (O1.E, O2.E, O3.E, O4.E, O5.E, O6.E, O7.E, O8.E) throws -> E)
-> Driver<E> {
let source = Observable.combineLatest(
source1.asDriver().asObservable(), source2.asDriver().asObservable(), source3.asDriver().asObservable(), source4.asDriver().asObservable(), source5.asDriver().asObservable(), source6.asDriver().asObservable(), source7.asDriver().asObservable(), source8.asDriver().asObservable(),
@ -320,3 +320,4 @@ extension Driver {
}
}

View File

@ -22,12 +22,12 @@ extension Driver {
- parameter resultSelector: Function to invoke for each series of elements at corresponding indexes in the sources.
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public static func zip<<%= (Array(1...i).map { "O\($0): DriverConvertibleType" }).joinWithSeparator(", ") %>>
(<%= (Array(1...i).map { "source\($0): O\($0)" }).joinWithSeparator(", _ ") %>, resultSelector: (<%= (Array(1...i).map { "O\($0).E" }).joinWithSeparator(", ") %>) throws -> E)
// @warn_unused_result(message:"http://git.io/rxs.uo")
public static func zip<<%= (Array(1...i).map { "O\($0): DriverConvertibleType" }).joined(separator: ", ") %>>
(<%= (Array(1...i).map { "_ source\($0): O\($0)" }).joined(separator: ", ") %>, resultSelector: @escaping (<%= (Array(1...i).map { "O\($0).E" }).joined(separator: ", ") %>) throws -> E)
-> Driver<E> {
let source = Observable.zip(
<%= (Array(1...i).map { "source\($0).asDriver().asObservable()" }).joinWithSeparator(", ") %>,
<%= (Array(1...i).map { "source\($0).asDriver().asObservable()" }).joined(separator: ", ") %>,
resultSelector: resultSelector
)
@ -42,12 +42,12 @@ extension Driver {
- parameter resultSelector: Function to invoke whenever any of the sources produces an element.
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public static func combineLatest<<%= (Array(1...i).map { "O\($0): DriverConvertibleType" }).joinWithSeparator(", ") %>>
(<%= (Array(1...i).map { "source\($0): O\($0)" }).joinWithSeparator(", _ ") %>, resultSelector: (<%= (Array(1...i).map { "O\($0).E" }).joinWithSeparator(", ") %>) throws -> E)
// @warn_unused_result(message:"http://git.io/rxs.uo")
public static func combineLatest<<%= (Array(1...i).map { "O\($0): DriverConvertibleType" }).joined(separator: ", ") %>>
(<%= (Array(1...i).map { "_ source\($0): O\($0)" }).joined(separator: ", ") %>, resultSelector: @escaping (<%= (Array(1...i).map { "O\($0).E" }).joined(separator: ", ") %>) throws -> E)
-> Driver<E> {
let source = Observable.combineLatest(
<%= (Array(1...i).map { "source\($0).asDriver().asObservable()" }).joinWithSeparator(", ") %>,
<%= (Array(1...i).map { "source\($0).asDriver().asObservable()" }).joined(separator: ", ") %>,
resultSelector: resultSelector
)
@ -55,4 +55,4 @@ extension Driver {
}
}
<% } %>
<% } %>

View File

@ -20,8 +20,8 @@ extension DriverConvertibleType {
- parameter selector: A transform function to apply to each source element.
- returns: An observable sequence whose elements are the result of invoking the transform function on each element of source.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func map<R>(selector: E -> R) -> Driver<R> {
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func map<R>(_ selector: @escaping (E) -> R) -> Driver<R> {
let source = self
.asObservable()
.map(selector)
@ -37,8 +37,8 @@ extension DriverConvertibleType {
- parameter predicate: A function to test each source element for a condition.
- returns: An observable sequence that contains elements from the input sequence that satisfy the condition.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func filter(predicate: (E) -> Bool) -> Driver<E> {
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func filter(_ predicate: @escaping (E) -> Bool) -> Driver<E> {
let source = self
.asObservable()
.filter(predicate)
@ -58,7 +58,7 @@ extension DriverConvertibleType where E : DriverConvertibleType {
- returns: The observable sequence that at any point in time produces the elements of the most recent inner observable sequence that has been received.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func switchLatest() -> Driver<E.E> {
let source: Observable<E.E> = self
.asObservable()
@ -80,8 +80,8 @@ extension DriverConvertibleType {
- returns: An observable sequence whose elements are the result of invoking the transform function on each element of source producing an
Observable of Observable sequences and that at any point in time produces the elements of the most recent inner observable sequence that has been received.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func flatMapLatest<R>(selector: (E) -> Driver<R>)
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func flatMapLatest<R>(_ selector: @escaping (E) -> Driver<R>)
-> Driver<R> {
let source: Observable<R> = self
.asObservable()
@ -100,8 +100,8 @@ extension DriverConvertibleType {
- parameter selector: A transform function to apply to element that was observed while no observable is executing in parallel.
- returns: An observable sequence whose elements are the result of invoking the one-to-many transform function on each element of the input sequence that was received while no other sequence was being calculated.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func flatMapFirst<R>(selector: (E) -> Driver<R>)
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func flatMapFirst<R>(_ selector: @escaping (E) -> Driver<R>)
-> Driver<R> {
let source: Observable<R> = self
.asObservable()
@ -119,11 +119,12 @@ extension DriverConvertibleType {
- parameter eventHandler: Action to invoke for each event in the observable sequence.
- returns: The source sequence with the side-effecting behavior applied.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func doOn(eventHandler: (Event<E>) -> Void)
// @warn_unused_result(message:"http://git.io/rxs.uo")
@available(*, deprecated, renamed: "do(onNext:onError:onCompleted:)")
public func doOn(_ eventHandler: @escaping (Event<E>) -> Void)
-> Driver<E> {
let source = self.asObservable()
.doOn(eventHandler)
.doOn(eventHandler)
return Driver(source)
}
@ -136,8 +137,9 @@ extension DriverConvertibleType {
- parameter onCompleted: Action to invoke upon graceful termination of the observable sequence.
- returns: The source sequence with the side-effecting behavior applied.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func doOn(onNext onNext: (E -> Void)? = nil, onError: (ErrorType -> Void)? = nil, onCompleted: (() -> Void)? = nil)
// @warn_unused_result(message:"http://git.io/rxs.uo")
@available(*, deprecated, renamed: "do(onNext:onError:onCompleted:)")
public func doOn(onNext: ((E) -> Void)? = nil, onError: ((Swift.Error) -> Void)? = nil, onCompleted: (() -> Void)? = nil)
-> Driver<E> {
let source = self.asObservable()
.doOn(onNext: onNext, onError: onError, onCompleted: onCompleted)
@ -151,10 +153,11 @@ extension DriverConvertibleType {
- parameter onNext: Action to invoke for each element in the observable sequence.
- returns: The source sequence with the side-effecting behavior applied.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func doOnNext(onNext: (E -> Void))
// @warn_unused_result(message:"http://git.io/rxs.uo")
@available(*, deprecated, renamed: "do(onNext:)")
public func doOnNext(_ onNext: @escaping (E) -> Void)
-> Driver<E> {
return self.doOn(onNext: onNext)
return self.do(onNext: onNext)
}
/**
@ -163,10 +166,30 @@ extension DriverConvertibleType {
- parameter onCompleted: Action to invoke upon graceful termination of the observable sequence.
- returns: The source sequence with the side-effecting behavior applied.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func doOnCompleted(onCompleted: (() -> Void))
// @warn_unused_result(message:"http://git.io/rxs.uo")
@available(*, deprecated, renamed: "do(onCompleted:)")
public func doOnCompleted(_ onCompleted: @escaping () -> Void)
-> Driver<E> {
return self.doOn(onCompleted: onCompleted)
return self.do(onCompleted: onCompleted)
}
/**
Invokes an action for each event in the observable sequence, and propagates all observer messages through the result sequence.
- parameter onNext: Action to invoke for each element in the observable sequence.
- parameter onError: Action to invoke upon errored termination of the observable sequence. This callback will never be invoked since driver can't error out.
- parameter onCompleted: Action to invoke upon graceful termination of the observable sequence.
- parameter onSubscribe: Action to invoke before subscribing to source observable sequence.
- parameter onDispose: Action to invoke after subscription to source observable has been disposed for any reason. It can be either because sequence terminates for some reason or observer subscription being disposed.
- returns: The source sequence with the side-effecting behavior applied.
*/
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func `do`(onNext: ((E) -> Void)? = nil, onError: ((Swift.Error) -> Void)? = nil, onCompleted: (() -> Void)? = nil, onSubscribe: (() -> ())? = nil, onDispose: (() -> ())? = nil)
-> Driver<E> {
let source = self.asObservable()
.do(onNext: onNext, onError: onError, onCompleted: onCompleted, onSubscribe: onSubscribe, onDispose: onDispose)
return Driver(source)
}
}
@ -179,8 +202,8 @@ extension DriverConvertibleType {
- parameter identifier: Identifier that is printed together with event description to standard output.
- returns: An observable sequence whose events are printed to standard output.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func debug(identifier: String? = nil, file: String = #file, line: UInt = #line, function: String = #function) -> Driver<E> {
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func debug(_ identifier: String? = nil, file: String = #file, line: UInt = #line, function: String = #function) -> Driver<E> {
let source = self.asObservable()
.debug(identifier, file: file, line: line, function: function)
return Driver(source)
@ -195,7 +218,7 @@ extension DriverConvertibleType where E: Equatable {
- returns: An observable sequence only containing the distinct contiguous elements, based on equality operator, from the source sequence.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func distinctUntilChanged()
-> Driver<E> {
let source = self.asObservable()
@ -213,8 +236,8 @@ extension DriverConvertibleType {
- parameter keySelector: A function to compute the comparison key for each element.
- returns: An observable sequence only containing the distinct contiguous elements, based on a computed key value, from the source sequence.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func distinctUntilChanged<K: Equatable>(keySelector: (E) -> K) -> Driver<E> {
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func distinctUntilChanged<K: Equatable>(_ keySelector: @escaping (E) -> K) -> Driver<E> {
let source = self.asObservable()
.distinctUntilChanged(keySelector, comparer: { $0 == $1 })
return Driver(source)
@ -226,8 +249,8 @@ extension DriverConvertibleType {
- parameter comparer: Equality comparer for computed key values.
- returns: An observable sequence only containing the distinct contiguous elements, based on `comparer`, from the source sequence.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func distinctUntilChanged(comparer: (lhs: E, rhs: E) -> Bool) -> Driver<E> {
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func distinctUntilChanged(_ comparer: @escaping (E, E) -> Bool) -> Driver<E> {
let source = self.asObservable()
.distinctUntilChanged({ $0 }, comparer: comparer)
return Driver(source)
@ -240,8 +263,8 @@ extension DriverConvertibleType {
- parameter comparer: Equality comparer for computed key values.
- returns: An observable sequence only containing the distinct contiguous elements, based on a computed key value and the comparer, from the source sequence.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func distinctUntilChanged<K>(keySelector: (E) -> K, comparer: (lhs: K, rhs: K) -> Bool) -> Driver<E> {
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func distinctUntilChanged<K>(_ keySelector: @escaping (E) -> K, comparer: @escaping (K, K) -> Bool) -> Driver<E> {
let source = self.asObservable()
.distinctUntilChanged(keySelector, comparer: comparer)
return Driver(source)
@ -258,8 +281,8 @@ extension DriverConvertibleType {
- parameter selector: A transform function to apply to each element.
- returns: An observable sequence whose elements are the result of invoking the one-to-many transform function on each element of the input sequence.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func flatMap<R>(selector: (E) -> Driver<R>) -> Driver<R> {
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func flatMap<R>(_ selector: @escaping (E) -> Driver<R>) -> Driver<R> {
let source = self.asObservable()
.flatMap(selector)
@ -276,7 +299,7 @@ extension DriverConvertibleType where E : DriverConvertibleType {
- parameter maxConcurrent: Maximum number of inner observable sequences being subscribed to concurrently.
- returns: The observable sequence that merges the elements of the observable sequences.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func merge() -> Driver<E.E> {
let source = self.asObservable()
.map { $0.asDriver() }
@ -289,8 +312,8 @@ extension DriverConvertibleType where E : DriverConvertibleType {
- returns: The observable sequence that merges the elements of the inner sequences.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func merge(maxConcurrent maxConcurrent: Int)
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func merge(maxConcurrent: Int)
-> Driver<E.E> {
let source = self.asObservable()
.map { $0.asDriver() }
@ -310,8 +333,8 @@ extension DriverConvertibleType {
- parameter dueTime: Throttling duration for each element.
- returns: The throttled sequence.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func throttle(dueTime: RxTimeInterval)
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func throttle(_ dueTime: RxTimeInterval)
-> Driver<E> {
let source = self.asObservable()
.throttle(dueTime, scheduler: driverObserveOnScheduler)
@ -327,8 +350,8 @@ extension DriverConvertibleType {
- parameter dueTime: Throttling duration for each element.
- returns: The throttled sequence.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func debounce(dueTime: RxTimeInterval)
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func debounce(_ dueTime: RxTimeInterval)
-> Driver<E> {
let source = self.asObservable()
.debounce(dueTime, scheduler: driverObserveOnScheduler)
@ -348,8 +371,8 @@ extension DriverConvertibleType {
- parameter accumulator: An accumulator function to be invoked on each element.
- returns: An observable sequence containing the accumulated values.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func scan<A>(seed: A, accumulator: (A, E) -> A)
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func scan<A>(_ seed: A, accumulator: @escaping (A, E) -> A)
-> Driver<A> {
let source = self.asObservable()
.scan(seed, accumulator: accumulator)
@ -358,29 +381,29 @@ extension DriverConvertibleType {
}
// MARK: concat
extension SequenceType where Generator.Element : DriverConvertibleType {
extension Sequence where Iterator.Element : DriverConvertibleType {
/**
Concatenates all observable sequences in the given sequence, as long as the previous observable sequence terminated successfully.
- returns: An observable sequence that contains the elements of each given sequence, in sequential order.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func concat()
-> Driver<Generator.Element.E> {
-> Driver<Iterator.Element.E> {
let source = self.lazy.map { $0.asDriver().asObservable() }.concat()
return Driver<Generator.Element.E>(source)
return Driver<Iterator.Element.E>(source)
}
}
extension CollectionType where Generator.Element : DriverConvertibleType {
extension Collection where Iterator.Element : DriverConvertibleType {
/**
Concatenates all observable sequences in the given sequence, as long as the previous observable sequence terminated successfully.
- returns: An observable sequence that contains the elements of each given sequence, in sequential order.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func concat()
-> Driver<Generator.Element.E> {
let source = self.map { $0.asDriver().asObservable() }.concat()
@ -389,7 +412,7 @@ extension CollectionType where Generator.Element : DriverConvertibleType {
}
// MARK: zip
extension CollectionType where Generator.Element : DriverConvertibleType {
extension Collection where Iterator.Element : DriverConvertibleType {
/**
Merges the specified observable sequences into one observable sequence by using the selector function whenever all of the observable sequences have produced an element at a corresponding index.
@ -397,15 +420,15 @@ extension CollectionType where Generator.Element : DriverConvertibleType {
- parameter resultSelector: Function to invoke for each series of elements at corresponding indexes in the sources.
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func zip<R>(resultSelector: [Generator.Element.E] throws -> R) -> Driver<R> {
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func zip<R>(_ resultSelector: @escaping ([Generator.Element.E]) throws -> R) -> Driver<R> {
let source = self.map { $0.asDriver().asObservable() }.zip(resultSelector)
return Driver<R>(source)
}
}
// MARK: combineLatest
extension CollectionType where Generator.Element : DriverConvertibleType {
extension Collection where Iterator.Element : DriverConvertibleType {
/**
Merges the specified observable sequences into one observable sequence by using the selector function whenever any of the observable sequences produces an element.
@ -413,8 +436,8 @@ extension CollectionType where Generator.Element : DriverConvertibleType {
- parameter resultSelector: Function to invoke whenever any of the sources produces an element.
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func combineLatest<R>(resultSelector: [Generator.Element.E] throws -> R) -> Driver<R> {
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func combineLatest<R>(_ resultSelector: @escaping ([Generator.Element.E]) throws -> R) -> Driver<R> {
let source = self.map { $0.asDriver().asObservable() }.combineLatest(resultSelector)
return Driver<R>(source)
}
@ -430,7 +453,7 @@ extension DriverConvertibleType {
- parameter resultSelector: Function to invoke for each element from the self combined with the latest element from the second source, if any.
- returns: An observable sequence containing the result of combining each element of the self with the latest element from the second source, if any, using the specified result selector function.
*/
public func withLatestFrom<SecondO: DriverConvertibleType, ResultType>(second: SecondO, resultSelector: (E, SecondO.E) -> ResultType) -> Driver<ResultType> {
public func withLatestFrom<SecondO: DriverConvertibleType, ResultType>(_ second: SecondO, resultSelector: @escaping (E, SecondO.E) -> ResultType) -> Driver<ResultType> {
let source = self.asObservable()
.withLatestFrom(second.asDriver(), resultSelector: resultSelector)
@ -443,7 +466,7 @@ extension DriverConvertibleType {
- parameter second: Second observable source.
- returns: An observable sequence containing the result of combining each element of the self with the latest element from the second source, if any, using the specified result selector function.
*/
public func withLatestFrom<SecondO: DriverConvertibleType>(second: SecondO) -> Driver<SecondO.E> {
public func withLatestFrom<SecondO: DriverConvertibleType>(_ second: SecondO) -> Driver<SecondO.E> {
let source = self.asObservable()
.withLatestFrom(second.asDriver())
@ -462,8 +485,8 @@ extension DriverConvertibleType {
- parameter count: The number of elements to skip before returning the remaining elements.
- returns: An observable sequence that contains the elements that occur after the specified index in the input sequence.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func skip(count: Int)
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func skip(_ count: Int)
-> Driver<E> {
let source = self.asObservable()
.skip(count)
@ -482,12 +505,12 @@ extension DriverConvertibleType {
- parameter element: Element to prepend to the specified sequence.
- returns: The source sequence prepended with the specified values.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func startWith(element: E)
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func startWith(_ element: E)
-> Driver<E> {
let source = self.asObservable()
.startWith(element)
return Driver(source)
}
}
}

View File

@ -11,30 +11,50 @@ 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.
- parameter observer: Observer that receives events.
- returns: Disposable object that can be used to unsubscribe the observer from the subject.
*/
@warn_unused_result(message="http://git.io/rxs.ud")
public func drive<O: ObserverType where O.E == E>(observer: O) -> Disposable {
MainScheduler.ensureExecutingOnScheduler()
// @warn_unused_result(message:"http://git.io/rxs.ud")
public func drive<O: ObserverType>(_ observer: O) -> Disposable where O.E == E {
MainScheduler.ensureExecutingOnScheduler(errorMessage: 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<E>) -> Disposable {
MainScheduler.ensureExecutingOnScheduler(errorMessage: driverErrorMessage)
return drive(onNext: { e in
variable.value = e
})
}
/**
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<R>(transformation: Observable<E> -> R) -> R {
MainScheduler.ensureExecutingOnScheduler()
// @warn_unused_result(message:"http://git.io/rxs.ud")
public func drive<R>(_ transformation: (Observable<E>) -> R) -> R {
MainScheduler.ensureExecutingOnScheduler(errorMessage: driverErrorMessage)
return transformation(self.asObservable())
}
@ -46,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<R1, R2>(with: Observable<E> -> R1 -> R2, curriedArgument: R1) -> R2 {
MainScheduler.ensureExecutingOnScheduler()
// @warn_unused_result(message:"http://git.io/rxs.ud")
public func drive<R1, R2>(_ with: (Observable<E>) -> (R1) -> R2, curriedArgument: R1) -> R2 {
MainScheduler.ensureExecutingOnScheduler(errorMessage: 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.
@ -68,22 +91,24 @@ extension DriverConvertibleType {
gracefully completed, errored, or if the generation is cancelled by disposing subscription)
- returns: Subscription object used to unsubscribe from the observable sequence.
*/
@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()
// @warn_unused_result(message:"http://git.io/rxs.ud")
public func drive(onNext: ((E) -> Void)? = nil, onCompleted: (() -> Void)? = nil, onDisposed: (() -> Void)? = nil) -> Disposable {
MainScheduler.ensureExecutingOnScheduler(errorMessage: 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()
return self.asObservable().subscribeNext(onNext)
// @warn_unused_result(message:"http://git.io/rxs.ud")
@available(*, deprecated, renamed: "drive(onNext:)")
public func driveNext(_ onNext: @escaping (E) -> Void) -> Disposable {
MainScheduler.ensureExecutingOnScheduler(errorMessage: driverErrorMessage)
return self.asObservable().subscribe(onNext: onNext)
}
}

View File

@ -19,12 +19,12 @@ public protocol DriverConvertibleType : ObservableConvertibleType {
/**
Converts self to `Driver`.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
func asDriver() -> Driver<E>
}
extension DriverConvertibleType {
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func asObservable() -> Observable<E> {
return asDriver().asObservable()
}
@ -75,7 +75,7 @@ public struct Driver<Element> : DriverConvertibleType {
/**
- returns: Built observable sequence.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func asObservable() -> Observable<E> {
return _source
}
@ -83,7 +83,7 @@ public struct Driver<Element> : DriverConvertibleType {
/**
- returns: `self`
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func asDriver() -> Driver<E> {
return self
}
@ -97,9 +97,9 @@ extension Driver {
- returns: An observable sequence with no elements.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public static func empty() -> Driver<E> {
return Driver(raw: Observable.empty().subscribeOn(driverSubscribeOnScheduler))
return Driver(Observable.empty().subscribeOn(driverSubscribeOnScheduler))
}
/**
@ -107,9 +107,9 @@ extension Driver {
- returns: An observable sequence whose observers will never get called.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public static func never() -> Driver<E> {
return Driver(raw: Observable.never().subscribeOn(driverSubscribeOnScheduler))
return Driver(Observable.never().subscribeOn(driverSubscribeOnScheduler))
}
/**
@ -118,9 +118,9 @@ extension Driver {
- parameter element: Single element in the resulting observable sequence.
- returns: An observable sequence containing the single specified element.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public static func just(element: E) -> Driver<E> {
return Driver(raw: Observable.just(element).subscribeOn(driverSubscribeOnScheduler))
// @warn_unused_result(message:"http://git.io/rxs.uo")
public static func just(_ element: E) -> Driver<E> {
return Driver(Observable.just(element).subscribeOn(driverSubscribeOnScheduler))
}
/**
@ -129,8 +129,8 @@ extension Driver {
- parameter observableFactory: Observable factory function to invoke for each observer that subscribes to the resulting sequence.
- returns: An observable sequence whose observers trigger an invocation of the given observable factory function.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public static func deferred(observableFactory: () -> Driver<E>)
// @warn_unused_result(message:"http://git.io/rxs.uo")
public static func deferred(_ observableFactory: @escaping () -> Driver<E>)
-> Driver<E> {
return Driver(Observable.deferred { observableFactory().asObservable() })
}
@ -143,14 +143,14 @@ extension Driver {
- parameter elements: Elements to generate.
- returns: The observable sequence whose elements are pulled from the given arguments.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public static func of(elements: E ...) -> Driver<E> {
let source = elements.toObservable(driverSubscribeOnScheduler)
// @warn_unused_result(message:"http://git.io/rxs.uo")
public static func of(_ elements: E ...) -> Driver<E> {
let source = Observable.from(elements, scheduler: driverSubscribeOnScheduler)
return Driver(raw: source)
}
}
extension Driver where Element : SignedIntegerType {
extension Driver where Element : SignedInteger {
/**
Returns an observable sequence that produces a value after each period, using the specified scheduler to run timers and to send out observer messages.
@ -159,8 +159,8 @@ extension Driver where Element : SignedIntegerType {
- 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)
// @warn_unused_result(message:"http://git.io/rxs.uo")
public static func interval(_ period: RxTimeInterval)
-> Driver<E> {
return Driver(Observable.interval(period, scheduler: driverObserveOnScheduler))
}
@ -168,7 +168,7 @@ extension Driver where Element : SignedIntegerType {
// MARK: timer
extension Driver where Element: SignedIntegerType {
extension Driver where Element: SignedInteger {
/**
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.
@ -178,8 +178,8 @@ extension Driver where Element: SignedIntegerType {
- 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)
// @warn_unused_result(message:"http://git.io/rxs.uo")
public static func timer(_ dueTime: RxTimeInterval, period: RxTimeInterval)
-> Driver<E> {
return Driver(Observable.timer(dueTime, period: period, scheduler: driverObserveOnScheduler))
}
@ -187,11 +187,11 @@ extension Driver where Element: SignedIntegerType {
/**
This method can be used in unit tests to ensure that driver is using mock schedulers instead of
maind schedulers.
main schedulers.
**This shouldn't be used in normal release builds.**
*/
public func driveOnScheduler(scheduler: SchedulerType, action: () -> ()) {
public func driveOnScheduler(_ scheduler: SchedulerType, action: () -> ()) {
let originalObserveOnScheduler = driverObserveOnScheduler
let originalSubscribeOnScheduler = driverSubscribeOnScheduler
@ -209,9 +209,9 @@ public func driveOnScheduler(scheduler: SchedulerType, action: () -> ()) {
driverSubscribeOnScheduler = originalSubscribeOnScheduler
}
func _forceCompilerToStopDoingInsaneOptimizationsThatBreakCode(scheduler: SchedulerType) {
func _forceCompilerToStopDoingInsaneOptimizationsThatBreakCode(_ scheduler: SchedulerType) {
let a: Int32 = 1
let b = 314 + Int32(rand() & 1)
let b = 314 + Int32(arc4random() & 1)
if a == b {
print(scheduler)
}

View File

@ -18,8 +18,8 @@ extension ObservableConvertibleType {
- parameter onErrorJustReturn: Element to return in case of error and after that complete the sequence.
- returns: Driving observable sequence.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func asDriver(onErrorJustReturn onErrorJustReturn: E) -> Driver<E> {
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func asDriver(onErrorJustReturn: E) -> Driver<E> {
let source = self
.asObservable()
.observeOn(driverObserveOnScheduler)
@ -33,8 +33,8 @@ extension ObservableConvertibleType {
- parameter onErrorDriveWith: Driver that continues to drive the sequence in case of error.
- returns: Driving observable sequence.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func asDriver(onErrorDriveWith onErrorDriveWith: Driver<E>) -> Driver<E> {
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func asDriver(onErrorDriveWith: Driver<E>) -> Driver<E> {
let source = self
.asObservable()
.observeOn(driverObserveOnScheduler)
@ -50,14 +50,14 @@ extension ObservableConvertibleType {
- parameter onErrorRecover: Calculates driver that continues to drive the sequence in case of error.
- returns: Driving observable sequence.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func asDriver(onErrorRecover onErrorRecover: (error: ErrorType) -> Driver<E>) -> Driver<E> {
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func asDriver(onErrorRecover: @escaping (_ error: Swift.Error) -> Driver<E>) -> Driver<E> {
let source = self
.asObservable()
.observeOn(driverObserveOnScheduler)
.catchError { error in
onErrorRecover(error: error).asObservable()
onErrorRecover(error).asObservable()
}
return Driver(source)
}
}
}

View File

@ -17,10 +17,10 @@ extension Variable {
- returns: Driving observable sequence.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func asDriver() -> Driver<E> {
let source = self.asObservable()
.observeOn(driverObserveOnScheduler)
return Driver(source)
}
}
}

View File

@ -16,9 +16,9 @@ Observer that enforces interface binding rules:
* can't bind errors (in debug builds binding of errors causes `fatalError` in release builds errors are being logged)
* ensures binding is performed on main thread
`InterfaceBindingObserver` doesn't retain target interface and in case owned interface element is released, element isn't bound.
`UIBindingObserver` doesn't retain target interface and in case owned interface element is released, element isn't bound.
*/
public class UIBindingObserver<UIElementType, Value where UIElementType: AnyObject> : ObserverType {
public class UIBindingObserver<UIElementType, Value> : ObserverType where UIElementType: AnyObject {
public typealias E = Value
weak var UIElement: UIElementType?
@ -28,7 +28,7 @@ public class UIBindingObserver<UIElementType, Value where UIElementType: AnyObje
/**
Initializes `ViewBindingObserver` using
*/
public init(UIElement: UIElementType, binding: (UIElementType, Value) -> Void) {
public init(UIElement: UIElementType, binding: @escaping (UIElementType, Value) -> Void) {
self.UIElement = UIElement
self.binding = binding
}
@ -36,18 +36,17 @@ public class UIBindingObserver<UIElementType, Value where UIElementType: AnyObje
/**
Binds next element to owner view as described in `binding`.
*/
public func on(event: Event<Value>) {
MainScheduler.ensureExecutingOnScheduler()
public func on(_ event: Event<Value>) {
MainScheduler.ensureExecutingOnScheduler(errorMessage: "Element can be bound to user interface only on MainThread.")
switch event {
case .Next(let element):
case .next(let element):
if let view = self.UIElement {
binding(view, element)
}
case .Error(let error):
case .error(let error):
bindingErrorToInterface(error)
break
case .Completed:
case .completed:
break
}
}
@ -60,4 +59,4 @@ public class UIBindingObserver<UIElementType, Value where UIElementType: AnyObje
public func asObserver() -> AnyObserver<Value> {
return AnyObserver(eventHandler: on)
}
}
}

View File

@ -19,7 +19,7 @@ Base class for `DelegateProxyType` protocol.
This implementation is not thread safe and can be used only from one thread (Main thread).
*/
public class DelegateProxy : _RXDelegateProxy {
open class DelegateProxy : _RXDelegateProxy {
private var subjectsForSelector = [Selector: PublishSubject<[AnyObject]>]()
@ -45,16 +45,52 @@ public class DelegateProxy : _RXDelegateProxy {
/**
Returns observable sequence of invocations of delegate methods.
Only methods that have `void` return value can be observed using this method because
those methods are used as a notification mechanism. It doesn't matter if they are optional
or not. Observing is performed by installing a hidden associated `PublishSubject` that is
used to dispatch messages to observers.
Delegate methods that have non `void` return value can't be observed directly using this method
because:
* those methods are not intended to be used as a notification mechanism, but as a behavior customization mechanism
* there is no sensible automatic way to determine a default return value
In case observing of delegate methods that have return type is required, it can be done by
manually installing a `PublishSubject` or `BehaviorSubject` and implementing delegate method.
e.g.
// delegate proxy part (RxScrollViewDelegateProxy)
let internalSubject = PublishSubject<CGPoint>
public func requiredDelegateMethod(scrollView: UIScrollView, arg1: CGPoint) -> Bool {
internalSubject.on(.next(arg1))
return self._forwardToDelegate?.requiredDelegateMethod?(scrollView, arg1: arg1) ?? defaultReturnValue
}
....
// reactive property implementation in a real class (`UIScrollView`)
public var property: Observable<CGPoint> {
let proxy = RxScrollViewDelegateProxy.proxyForObject(base)
return proxy.internalSubject.asObservable()
}
**In case calling this method prints "Delegate proxy is already implementing `\(selector)`,
a more performant way of registering might exist.", that means that manual observing method
is required analog to the example above because delegate method has already been implemented.**
- parameter selector: Selector used to filter observed invocations of delegate methods.
- returns: Observable sequence of arguments passed to `selector` method.
*/
public func observe(selector: Selector) -> Observable<[AnyObject]> {
if hasWiredImplementationForSelector(selector) {
public func observe(_ selector: Selector) -> Observable<[AnyObject]> {
if hasWiredImplementation(for: selector) {
print("Delegate proxy is already implementing `\(selector)`, a more performant way of registering might exist.")
}
if !self.respondsToSelector(selector) {
if !self.responds(to: selector) {
rxFatalError("This class doesn't respond to selector \(selector)")
}
@ -72,8 +108,8 @@ public class DelegateProxy : _RXDelegateProxy {
// proxy
public override func interceptedSelector(selector: Selector, withArguments arguments: [AnyObject]!) {
subjectsForSelector[selector]?.on(.Next(arguments))
open override func interceptedSelector(_ selector: Selector, withArguments arguments: [Any]) {
subjectsForSelector[selector]?.on(.next(arguments as [AnyObject]))
}
/**
@ -81,7 +117,7 @@ public class DelegateProxy : _RXDelegateProxy {
- returns: Associated object tag.
*/
public class func delegateAssociatedObjectTag() -> UnsafePointer<Void> {
public class func delegateAssociatedObjectTag() -> UnsafeRawPointer {
return _pointer(&delegateAssociatedTag)
}
@ -90,7 +126,7 @@ public class DelegateProxy : _RXDelegateProxy {
- returns: Initialized instance of `self`.
*/
public class func createProxyForObject(object: AnyObject) -> AnyObject {
public class func createProxyForObject(_ object: AnyObject) -> AnyObject {
return self.init(parentObject: object)
}
@ -100,9 +136,9 @@ public class DelegateProxy : _RXDelegateProxy {
- parameter object: Object that can have assigned delegate proxy.
- returns: Assigned delegate proxy or `nil` if no delegate proxy is assigned.
*/
public class func assignedProxyFor(object: AnyObject) -> AnyObject? {
let maybeDelegate: AnyObject? = objc_getAssociatedObject(object, self.delegateAssociatedObjectTag())
return castOptionalOrFatalError(maybeDelegate)
public class func assignedProxyFor(_ object: AnyObject) -> AnyObject? {
let maybeDelegate = objc_getAssociatedObject(object, self.delegateAssociatedObjectTag())
return castOptionalOrFatalError(maybeDelegate.map { $0 as AnyObject })
}
/**
@ -111,8 +147,8 @@ public class DelegateProxy : _RXDelegateProxy {
- parameter object: Object that can have assigned delegate proxy.
- parameter proxy: Delegate proxy object to assign to `object`.
*/
public class func assignProxy(proxy: AnyObject, toObject object: AnyObject) {
precondition(proxy.isKindOfClass(self.classForCoder()))
public class func assignProxy(_ proxy: AnyObject, toObject object: AnyObject) {
precondition(proxy.isKind(of: self.classForCoder()))
objc_setAssociatedObject(object, self.delegateAssociatedObjectTag(), proxy, .OBJC_ASSOCIATION_RETAIN)
}
@ -124,8 +160,8 @@ public class DelegateProxy : _RXDelegateProxy {
- parameter forwardToDelegate: Reference of delegate that receives all messages through `self`.
- parameter retainDelegate: Should `self` retain `forwardToDelegate`.
*/
public func setForwardToDelegate(delegate: AnyObject?, retainDelegate: Bool) {
self._setForwardToDelegate(delegate, retainDelegate: retainDelegate)
public func setForwardToDelegate(_ delegate: AnyObject?, retainDelegate: Bool) {
self._setForward(toDelegate: delegate, retainDelegate: retainDelegate)
}
/**
@ -140,7 +176,7 @@ public class DelegateProxy : _RXDelegateProxy {
deinit {
for v in subjectsForSelector.values {
v.on(.Completed)
v.on(.completed)
}
#if TRACE_RESOURCES
OSAtomicDecrement32(&resourceCount)
@ -149,7 +185,7 @@ public class DelegateProxy : _RXDelegateProxy {
// MARK: Pointer
class func _pointer(p: UnsafePointer<Void>) -> UnsafePointer<Void> {
class func _pointer(_ p: UnsafeRawPointer) -> UnsafeRawPointer {
return p
}
}
}

View File

@ -68,9 +68,9 @@ every view has a corresponding delegate virtual factory method.
In case of UITableView / UIScrollView, there is
extensions UIScrollView {
public func rx_createDelegateProxy() -> RxScrollViewDelegateProxy {
return RxScrollViewDelegateProxy(view: self)
extension UIScrollView {
public func createRxDelegateProxy() -> RxScrollViewDelegateProxy {
return RxScrollViewDelegateProxy(parentObject: base)
}
....
@ -78,7 +78,7 @@ In case of UITableView / UIScrollView, there is
and override in UITableView
extension UITableView {
public override func rx_createDelegateProxy() -> RxScrollViewDelegateProxy {
public override func createRxDelegateProxy() -> RxScrollViewDelegateProxy {
....
@ -87,7 +87,7 @@ public protocol DelegateProxyType : AnyObject {
/**
Creates new proxy for target object.
*/
static func createProxyForObject(object: AnyObject) -> AnyObject
static func createProxyForObject(_ object: AnyObject) -> AnyObject
/**
Returns assigned proxy for object.
@ -95,7 +95,7 @@ public protocol DelegateProxyType : AnyObject {
- parameter object: Object that can have assigned delegate proxy.
- returns: Assigned delegate proxy or `nil` if no delegate proxy is assigned.
*/
static func assignedProxyFor(object: AnyObject) -> AnyObject?
static func assignedProxyFor(_ object: AnyObject) -> AnyObject?
/**
Assigns proxy to object.
@ -103,7 +103,7 @@ public protocol DelegateProxyType : AnyObject {
- parameter object: Object that can have assigned delegate proxy.
- parameter proxy: Delegate proxy object to assign to `object`.
*/
static func assignProxy(proxy: AnyObject, toObject object: AnyObject)
static func assignProxy(_ proxy: AnyObject, toObject object: AnyObject)
/**
Returns designated delegate property for object.
@ -115,7 +115,7 @@ public protocol DelegateProxyType : AnyObject {
- parameter object: Object that has delegate property.
- returns: Value of delegate property.
*/
static func currentDelegateFor(object: AnyObject) -> AnyObject?
static func currentDelegateFor(_ object: AnyObject) -> AnyObject?
/**
Sets designated delegate property for object.
@ -127,7 +127,7 @@ public protocol DelegateProxyType : AnyObject {
- parameter toObject: Object that has delegate property.
- parameter delegate: Delegate value.
*/
static func setCurrentDelegate(delegate: AnyObject?, toObject object: AnyObject)
static func setCurrentDelegate(_ delegate: AnyObject?, toObject object: AnyObject)
/**
Returns reference of normal delegate that receives all forwarded messages
@ -144,88 +144,115 @@ public protocol DelegateProxyType : AnyObject {
- parameter forwardToDelegate: Reference of delegate that receives all messages through `self`.
- parameter retainDelegate: Should `self` retain `forwardToDelegate`.
*/
func setForwardToDelegate(forwardToDelegate: AnyObject?, retainDelegate: Bool)
func setForwardToDelegate(_ forwardToDelegate: AnyObject?, retainDelegate: Bool)
}
/**
Returns existing proxy for object or installs new instance of delegate proxy.
- parameter object: Target object on which to install delegate proxy.
- returns: Installed instance of delegate proxy.
extension UISearchBar {
public var rx_delegate: DelegateProxy {
return proxyForObject(RxSearchBarDelegateProxy.self, self)
}
public var rx_text: ControlProperty<String> {
let source: Observable<String> = self.rx_delegate.observe("searchBar:textDidChange:")
...
}
}
*/
public func proxyForObject<P: DelegateProxyType>(type: P.Type, _ object: AnyObject) -> P {
MainScheduler.ensureExecutingOnScheduler()
let maybeProxy = P.assignedProxyFor(object) as? P
let proxy: P
if maybeProxy == nil {
proxy = P.createProxyForObject(object) as! P
P.assignProxy(proxy, toObject: object)
assert(P.assignedProxyFor(object) === proxy)
}
else {
proxy = maybeProxy!
}
let currentDelegate: AnyObject? = P.currentDelegateFor(object)
if currentDelegate !== proxy {
proxy.setForwardToDelegate(currentDelegate, retainDelegate: false)
P.setCurrentDelegate(proxy, toObject: object)
assert(P.currentDelegateFor(object) === proxy)
assert(proxy.forwardToDelegate() === currentDelegate)
}
return proxy
@available(*, deprecated:2.5, renamed:"DelegateProxyType.proxyForObject", message:"You can just use normal static protocol extension. E.g. `RxScrollViewDelegateProxy.proxyForObject`")
public func proxyForObject<P: DelegateProxyType>(_ type: P.Type, _ object: AnyObject) -> P {
return P.proxyForObject(object)
}
func installDelegate<P: DelegateProxyType>(proxy: P, delegate: AnyObject, retainDelegate: Bool, onProxyForObject object: AnyObject) -> Disposable {
weak var weakDelegate: AnyObject? = delegate
assert(proxy.forwardToDelegate() === nil, "There is already a delegate set -> `\(proxy.forwardToDelegate())` for object -> `\(object)`.\nMaybe delegate was already set in `xib` or `storyboard` and now it's being overwritten in code.")
proxy.setForwardToDelegate(delegate, retainDelegate: retainDelegate)
// refresh properties after delegate is set
// some views like UITableView cache `respondsToSelector`
P.setCurrentDelegate(nil, toObject: object)
P.setCurrentDelegate(proxy, toObject: object)
assert(proxy.forwardToDelegate() === delegate, "Setting of delegate failed")
return AnonymousDisposable {
extension DelegateProxyType {
/**
Returns existing proxy for object or installs new instance of delegate proxy.
- parameter object: Target object on which to install delegate proxy.
- returns: Installed instance of delegate proxy.
extension Reactive where Base: UISearchBar {
public var delegate: DelegateProxy {
return RxSearchBarDelegateProxy.proxyForObject(base)
}
public var text: ControlProperty<String> {
let source: Observable<String> = self.delegate.observe(#selector(UISearchBarDelegate.searchBar(_:textDidChange:)))
...
}
}
*/
public static func proxyForObject(_ object: AnyObject) -> Self {
MainScheduler.ensureExecutingOnScheduler()
let maybeProxy = Self.assignedProxyFor(object) as? Self
let proxy: Self
if let existingProxy = maybeProxy {
proxy = existingProxy
}
else {
proxy = Self.createProxyForObject(object) as! Self
Self.assignProxy(proxy, toObject: object)
assert(Self.assignedProxyFor(object) === proxy)
}
let currentDelegate: AnyObject? = Self.currentDelegateFor(object)
if currentDelegate !== proxy {
proxy.setForwardToDelegate(currentDelegate, retainDelegate: false)
assert(proxy.forwardToDelegate() === currentDelegate)
Self.setCurrentDelegate(proxy, toObject: object)
assert(Self.currentDelegateFor(object) === proxy)
assert(proxy.forwardToDelegate() === currentDelegate)
}
let delegate: AnyObject? = weakDelegate
return proxy
}
/**
Sets forward delegate for `DelegateProxyType` associated with a specific object and return disposable that can be used to unset the forward to delegate.
Using this method will also make sure that potential original object cached selectors are cleared and will report any accidental forward delegate mutations.
- parameter forwardDelegate: Delegate object to set.
- parameter retainDelegate: Retain `forwardDelegate` while it's being set.
- parameter onProxyForObject: Object that has `delegate` property.
- returns: Disposable object that can be used to clear forward delegate.
*/
public static func installForwardDelegate(_ forwardDelegate: AnyObject, retainDelegate: Bool, onProxyForObject object: AnyObject) -> Disposable {
weak var weakForwardDelegate: AnyObject? = forwardDelegate
let proxy = Self.proxyForObject(object)
assert(delegate == nil || proxy.forwardToDelegate() === delegate, "Delegate was changed from time it was first set. Current \(proxy.forwardToDelegate()), and it should have been \(proxy)")
assert(proxy.forwardToDelegate() === nil, "This is a feature to warn you that there is already a delegate (or data source) set somewhere previously. The action you are trying to perform will clear that delegate (data source) and that means that some of your features that depend on that delegate (data source) being set will likely stop working.\n" +
"If you are ok with this, try to set delegate (data source) to `nil` in front of this operation.\n" +
" This is the source object value: \(object)\n" +
" This this the original delegate (data source) value: \(proxy.forwardToDelegate()!)\n" +
"Hint: Maybe delegate was already set in xib or storyboard and now it's being overwritten in code.\n")
proxy.setForwardToDelegate(forwardDelegate, retainDelegate: retainDelegate)
proxy.setForwardToDelegate(nil, retainDelegate: retainDelegate)
// refresh properties after delegate is set
// some views like UITableView cache `respondsToSelector`
Self.setCurrentDelegate(nil, toObject: object)
Self.setCurrentDelegate(proxy, toObject: object)
assert(proxy.forwardToDelegate() === forwardDelegate, "Setting of delegate failed:\ncurrent:\n\(proxy.forwardToDelegate())\nexpected:\n\(forwardDelegate)")
return Disposables.create {
MainScheduler.ensureExecutingOnScheduler()
let delegate: AnyObject? = weakForwardDelegate
assert(delegate == nil || proxy.forwardToDelegate() === delegate, "Delegate was changed from time it was first set. Current \(proxy.forwardToDelegate()), and it should have been \(proxy)")
proxy.setForwardToDelegate(nil, retainDelegate: retainDelegate)
}
}
}
extension ObservableType {
func subscribeProxyDataSourceForObject<P: DelegateProxyType>(object: AnyObject, dataSource: AnyObject, retainDataSource: Bool, binding: (P, Event<E>) -> Void)
func subscribeProxyDataSource<P: DelegateProxyType>(ofObject object: AnyObject, dataSource: AnyObject, retainDataSource: Bool, binding: @escaping (P, Event<E>) -> Void)
-> Disposable {
let proxy = proxyForObject(P.self, object)
let disposable = installDelegate(proxy, delegate: dataSource, retainDelegate: retainDataSource, onProxyForObject: object)
let proxy = P.proxyForObject(object)
let disposable = P.installForwardDelegate(dataSource, retainDelegate: retainDataSource, onProxyForObject: object)
let subscription = self.asObservable()
// source can't ever end, otherwise it will release the subscriber
.catchError { error in
bindingErrorToInterface(error)
return Observable.empty()
}
// source can never end, otherwise it would release the subscriber, and deallocate the data source
.concat(Observable.never())
.subscribe { [weak object] (event: Event<E>) in
MainScheduler.ensureExecutingOnScheduler()
@ -237,16 +264,16 @@ extension ObservableType {
binding(proxy, event)
switch event {
case .Error(let error):
case .error(let error):
bindingErrorToInterface(error)
disposable.dispose()
case .Completed:
case .completed:
disposable.dispose()
default:
break
}
}
return StableCompositeDisposable.create(subscription, disposable)
return Disposables.create(subscription, disposable)
}
}

View File

@ -15,7 +15,7 @@ extension Int : KVORepresentable {
Constructs `Self` using KVO value.
*/
public init?(KVOValue: KVOType) {
self.init(KVOValue.integerValue)
self.init(KVOValue.int32Value)
}
}
@ -26,7 +26,7 @@ extension Int32 : KVORepresentable {
Constructs `Self` using KVO value.
*/
public init?(KVOValue: KVOType) {
self.init(KVOValue.intValue)
self.init(KVOValue.int32Value)
}
}
@ -37,7 +37,7 @@ extension Int64 : KVORepresentable {
Constructs `Self` using KVO value.
*/
public init?(KVOValue: KVOType) {
self.init(KVOValue.longLongValue)
self.init(KVOValue.int64Value)
}
}
@ -48,7 +48,7 @@ extension UInt : KVORepresentable {
Constructs `Self` using KVO value.
*/
public init?(KVOValue: KVOType) {
self.init(KVOValue.unsignedLongValue)
self.init(KVOValue.uintValue)
}
}
@ -59,7 +59,7 @@ extension UInt32 : KVORepresentable {
Constructs `Self` using KVO value.
*/
public init?(KVOValue: KVOType) {
self.init(KVOValue.unsignedIntValue)
self.init(KVOValue.uint32Value)
}
}
@ -70,7 +70,7 @@ extension UInt64 : KVORepresentable {
Constructs `Self` using KVO value.
*/
public init?(KVOValue: KVOType) {
self.init(KVOValue.unsignedLongLongValue)
self.init(KVOValue.uint64Value)
}
}
@ -90,4 +90,4 @@ extension RawRepresentable where RawValue: KVORepresentable {
self.init(rawValue: rawValue)
}
}
}

View File

@ -12,7 +12,7 @@ import Foundation
Simple logging settings for RxCocoa library.
*/
public struct Logging {
public typealias LogURLRequest = (NSURLRequest) -> Bool
public typealias LogURLRequest = (URLRequest) -> Bool
/**
Log URL requests to standard output in curl format.
@ -24,4 +24,4 @@ public struct Logging {
return false
#endif
}
}
}

View File

@ -19,12 +19,12 @@ import RxSwift
#endif
#if os(iOS) || os(OSX) || os(tvOS)
extension NSLayoutConstraint {
extension Reactive where Base: NSLayoutConstraint {
/**
Bindable sink for `constant` property.
*/
public var rx_constant: AnyObserver<CGFloat> {
return UIBindingObserver(UIElement: self) { constraint, constant in
public var constant: AnyObserver<CGFloat> {
return UIBindingObserver(UIElement: self.base) { constraint, constant in
constraint.constant = constant
}.asObserver()
}
@ -33,9 +33,9 @@ extension NSLayoutConstraint {
Bindable sink for `active` property.
*/
@available(iOS 8, OSX 10.10, *)
public var rx_active: AnyObserver<Bool> {
return UIBindingObserver(UIElement: self) { constraint, value in
constraint.active = value
public var active: AnyObserver<Bool> {
return UIBindingObserver(UIElement: self.base) { constraint, value in
constraint.isActive = value
}.asObserver()
}
}

View File

@ -22,8 +22,8 @@ extension ObservableType {
- parameter observer: Observer that receives events.
- returns: Disposable object that can be used to unsubscribe the observer.
*/
@warn_unused_result(message="http://git.io/rxs.ud")
public func bindTo<O: ObserverType where O.E == E>(observer: O) -> Disposable {
// @warn_unused_result(message: "http://git.io/rxs.ud")
public func bindTo<O: ObserverType>(_ observer: O) -> Disposable where O.E == E {
return self.subscribe(observer)
}
@ -36,20 +36,20 @@ extension ObservableType {
- parameter variable: Target variable for sequence elements.
- returns: Disposable object that can be used to unsubscribe the observer.
*/
@warn_unused_result(message="http://git.io/rxs.ud")
public func bindTo(variable: Variable<E>) -> Disposable {
// @warn_unused_result(message: "http://git.io/rxs.ud")
public func bindTo(_ variable: Variable<E>) -> Disposable {
return subscribe { e in
switch e {
case let .Next(element):
case let .next(element):
variable.value = element
case let .Error(error):
case let .error(error):
let error = "Binding error to variable: \(error)"
#if DEBUG
rxFatalError(error)
#else
print(error)
#endif
case .Completed:
case .completed:
break
}
}
@ -61,8 +61,8 @@ extension ObservableType {
- parameter binder: Function used to bind elements from `self`.
- returns: Object representing subscription.
*/
@warn_unused_result(message="http://git.io/rxs.ud")
public func bindTo<R>(binder: Self -> R) -> R {
// @warn_unused_result(message: "http://git.io/rxs.ud")
public func bindTo<R>(_ binder: (Self) -> R) -> R {
return binder(self)
}
@ -78,8 +78,8 @@ extension ObservableType {
- 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 bindTo<R1, R2>(binder: Self -> R1 -> R2, curriedArgument: R1) -> R2 {
// @warn_unused_result(message: "http://git.io/rxs.ud")
public func bindTo<R1, R2>(_ binder: (Self) -> (R1) -> R2, curriedArgument: R1) -> R2 {
return binder(self)(curriedArgument)
}
@ -93,8 +93,8 @@ extension ObservableType {
- 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 bindNext(onNext: E -> Void) -> Disposable {
// @warn_unused_result(message: "http://git.io/rxs.ud")
public func bindNext(_ onNext: @escaping (E) -> Void) -> Disposable {
return subscribe(onNext: onNext, onError: { error in
let error = "Binding error: \(error)"
#if DEBUG

View File

@ -45,9 +45,9 @@ class ControlTarget: RxTarget {
super.init()
control.addTarget(self, action: selector, forControlEvents: controlEvents)
control.addTarget(self, action: selector, for: controlEvents)
let method = self.methodForSelector(selector)
let method = self.method(for: selector)
if method == nil {
rxFatalError("Can't find method")
}
@ -64,15 +64,15 @@ class ControlTarget: RxTarget {
control.target = self
control.action = selector
let method = self.methodForSelector(selector)
let method = self.method(for: selector)
if method == nil {
rxFatalError("Can't find method")
}
}
#endif
func eventHandler(sender: Control!) {
if let callback = self.callback, control = self.control {
func eventHandler(_ sender: Control!) {
if let callback = self.callback, let control = self.control {
callback(control)
}
}
@ -80,7 +80,7 @@ class ControlTarget: RxTarget {
override func dispose() {
super.dispose()
#if os(iOS) || os(tvOS)
self.control?.removeTarget(self, action: self.selector, forControlEvents: self.controlEvents)
self.control?.removeTarget(self, action: self.selector, for: self.controlEvents)
#elseif os(OSX)
self.control?.target = nil
self.control?.action = nil

View File

@ -12,13 +12,13 @@ import RxSwift
#endif
class DeallocObservable {
let _subject = ReplaySubject<Void>.create(bufferSize: 1)
let _subject = ReplaySubject<Void>.create(bufferSize:1)
init() {
}
deinit {
_subject.on(.Next(()))
_subject.on(.Completed)
_subject.on(.next(()))
_subject.on(.completed)
}
}

View File

@ -33,32 +33,29 @@ class KVOObservable<Element>
}
}
func subscribe<O : ObserverType where O.E == Element?>(observer: O) -> Disposable {
func subscribe<O : ObserverType>(_ observer: O) -> Disposable where O.E == Element? {
let observer = KVOObserver(parent: self) { (value) in
if value as? NSNull != nil {
observer.on(.Next(nil))
observer.on(.next(nil))
return
}
observer.on(.Next(value as? Element))
observer.on(.next(value as? Element))
}
return AnonymousDisposable {
observer.dispose()
}
return Disposables.create(with: observer.dispose)
}
}
#if !DISABLE_SWIZZLING
func observeWeaklyKeyPathFor(target: NSObject, keyPath: String, options: NSKeyValueObservingOptions) -> Observable<AnyObject?> {
let components = keyPath.componentsSeparatedByString(".").filter { $0 != "self" }
func observeWeaklyKeyPathFor(_ target: NSObject, keyPath: String, options: NSKeyValueObservingOptions) -> Observable<AnyObject?> {
let components = keyPath.components(separatedBy: ".").filter { $0 != "self" }
let observable = observeWeaklyKeyPathFor(target, keyPathSections: components, options: options)
.distinctUntilChanged { $0 === $1 }
.finishWithNilWhenDealloc(target)
if !options.intersect(.Initial).isEmpty {
if !options.intersection(.initial).isEmpty {
return observable
}
else {
@ -71,14 +68,14 @@ func observeWeaklyKeyPathFor(target: NSObject, keyPath: String, options: NSKeyVa
// Identifiers can't contain `,`, so the only place where `,` can appear
// is as a delimiter.
// This means there is `W` as element in an array of property attributes.
func isWeakProperty(properyRuntimeInfo: String) -> Bool {
return properyRuntimeInfo.rangeOfString(",W,") != nil
func isWeakProperty(_ properyRuntimeInfo: String) -> Bool {
return properyRuntimeInfo.range(of: ",W,") != nil
}
extension ObservableType where E == AnyObject? {
func finishWithNilWhenDealloc(target: NSObject)
func finishWithNilWhenDealloc(_ target: NSObject)
-> Observable<AnyObject?> {
let deallocating = target.rx_deallocating
let deallocating = target.rx.deallocating
return deallocating
.map { _ in
@ -90,7 +87,7 @@ extension ObservableType where E == AnyObject? {
}
func observeWeaklyKeyPathFor(
target: NSObject,
_ target: NSObject,
keyPathSections: [String],
options: NSKeyValueObservingOptions
) -> Observable<AnyObject?> {
@ -102,13 +99,13 @@ func observeWeaklyKeyPathFor(
let property = class_getProperty(object_getClass(target), propertyName)
if property == nil {
return Observable.error(RxCocoaError.InvalidPropertyName(object: target, propertyName: propertyName))
return Observable.error(RxCocoaError.invalidPropertyName(object: target, propertyName: propertyName))
}
let propertyAttributes = property_getAttributes(property)
// should dealloc hook be in place if week property, or just create strong reference because it doesn't matter
let isWeak = isWeakProperty(String.fromCString(propertyAttributes) ?? "")
let propertyObservable = KVOObservable(object: target, keyPath: propertyName, options: options.union(.Initial), retainTarget: false) as KVOObservable<AnyObject>
let isWeak = isWeakProperty(propertyAttributes.map(String.init) ?? "")
let propertyObservable = KVOObservable(object: target, keyPath: propertyName, options: options.union(.initial), retainTarget: false) as KVOObservable<AnyObject>
// KVO recursion for value changes
return propertyObservable
@ -121,7 +118,7 @@ func observeWeaklyKeyPathFor(
let strongTarget: AnyObject? = weakTarget
if nextObject == nil {
return Observable.error(RxCocoaError.InvalidObjectOnKeyPath(object: nextTarget!, sourceObject: strongTarget ?? NSNull(), propertyName: propertyName))
return Observable.error(RxCocoaError.invalidObjectOnKeyPath(object: nextTarget!, sourceObject: strongTarget ?? NSNull(), propertyName: propertyName))
}
// if target is alive, then send change

View File

@ -20,7 +20,7 @@ protocol KVOObservableProtocol {
class KVOObserver : _RXKVOObserver
, Disposable {
typealias Callback = (AnyObject?) -> Void
typealias Callback = @escaping (Any?) -> Void
var retainSelf: KVOObserver? = nil
@ -43,4 +43,4 @@ class KVOObserver : _RXKVOObserver
OSAtomicDecrement32(&resourceCount)
#endif
}
}
}

View File

@ -29,8 +29,8 @@ import Foundation
init() {
}
@objc func messageSentWithParameters(parameters: [AnyObject]) -> Void {
_subject.on(.Next())
@objc func messageSent(withParameters parameters: [Any]) -> Void {
_subject.on(.next())
}
func asObservable() -> Observable<()> {
@ -38,7 +38,7 @@ import Foundation
}
deinit {
_subject.on(.Completed)
_subject.on(.completed)
}
}
@ -58,8 +58,8 @@ import Foundation
init() {
}
@objc func messageSentWithParameters(parameters: [AnyObject]) -> Void {
_subject.on(.Next(parameters))
@objc func messageSent(withParameters parameters: [Any]) -> Void {
_subject.on(.next(parameters as [AnyObject]))
}
func asObservable() -> Observable<[AnyObject]> {
@ -67,7 +67,7 @@ import Foundation
}
deinit {
_subject.on(.Completed)
_subject.on(.completed)
}
}

View File

@ -11,7 +11,7 @@ import Foundation
import RxSwift
#endif
extension NSNotificationCenter {
extension Reactive where Base: NotificationCenter {
/**
Transforms notifications posted to notification center to observable sequence of notifications.
@ -19,16 +19,16 @@ extension NSNotificationCenter {
- parameter object: Optional object used to filter notifications.
- returns: Observable sequence of posted notifications.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func rx_notification(name: String?, object: AnyObject? = nil) -> Observable<NSNotification> {
// @warn_unused_result(message:"http://git.io/rxs.uo")
public func notification(_ name: Notification.Name, object: AnyObject? = nil) -> Observable<Notification> {
return Observable.create { [weak object] observer in
let nsObserver = self.addObserverForName(name, object: object, queue: nil) { notification in
observer.on(.Next(notification))
let nsObserver = self.base.addObserver(forName: name, object: object, queue: nil) { notification in
observer.on(.next(notification))
}
return AnonymousDisposable {
self.removeObserver(nsObserver)
return Disposables.create {
self.base.removeObserver(nsObserver)
}
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More