Updates documentation.

This commit is contained in:
Krunoslav Zaher 2015-09-04 23:15:16 +02:00
parent 35eb5e580b
commit 6139b16ca3
16 changed files with 370 additions and 711 deletions

View File

@ -13,8 +13,10 @@ All notable changes to this project will be documented in this file.
* Change from `disposeBag.addDisposable` to `disposable.addDisposableTo`
* Changes in RxCocoa extensions to enable fluent style
* Rename of `do*` to `doOn*`
* Deprecates `returnElement` in favor of `just`
* Deprecates `aggregate` in favor of `reduce`
* Deprecates `variable` in favor of `shareReplay(1)` (to be consistent with RxJS version)
* Method `next` on `Variable` is now `sendNext`
#### Fixed

View File

@ -5,9 +5,11 @@ The migration should be pretty straightforward. The changes are mostly cosmetic,
* Find replace all `>- ` to `.`
* Find replace all "variable" to "shareReplay(1)"
* Find replace all "catch" to "catchErrorResumeNext"
* Find replace all "returnElement" to "just"
* 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 `sendNext`
* If you want to use `tableViews`/`collectionViews`, this is the basic use case now
```swift

View File

@ -456,8 +456,9 @@ Open Rx.xcworkspace, choose `RxExample` and hit run. This method will build ever
# Podfile
use_frameworks!
pod 'RxSwift'
pod 'RxCocoa'
pod 'RxSwift', '~> 2.0-alpha'
pod 'RxCocoa', '~> 2.0-alpha'
pod 'RxBlocking', '~> 2.0-alpha'
```
type in `Podfile` directory
@ -471,7 +472,7 @@ $ pod install
Add this to `Cartfile`
```
git "git@github.com:ReactiveX/RxSwift.git"
git "git@github.com:ReactiveX/RxSwift.git" "2.0-alpha.1"
```
```

View File

@ -6,11 +6,13 @@ import RxSwift
## Combination operators
Operators that work with multiple source Observables to create a single Observable.
*/
/*:
### `startWith`
Return an observeble which emits a specified item before emitting the items from the source Observable.
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)
@ -18,79 +20,67 @@ Return an observeble which emits a specified item before emitting the items from
*/
example("startWith") {
let aggregateSubscriber = sequenceOf(4, 5, 6, 7, 8, 9)
let subscription = sequenceOf(4, 5, 6, 7, 8, 9)
.startWith(3)
.startWith(2)
.startWith(1)
.startWith(0)
.subscribeNext { int in
print(int)
.subscribe {
print($0)
}
}
/*:
### `combineLatest`
Takes several source Obserbables and a closure as parameters, returns an Observable which emits the latest items of each source Obsevable, procesed through the closure.
Once each source Observables have each emitted an item, `combineLatest` emits an item every time either source Observable emits an item.
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 )
The next example shows how
*/
example("combineLatest 1st") {
example("combineLatest 1") {
let intOb1 = PublishSubject<String>()
let intOb2 = PublishSubject<Int>()
combineLatest(intOb1, intOb2) {
"\($0) \($1)"
}
.subscribeNext {
.subscribe {
print($0)
}
print("send A to first channel")
intOb1.on(.Next("A"))
print("note that nothing outputs")
print("\nsend 1 to second channel")
intOb2.on(.Next(1))
print("now that there is something in both channels, there is output")
print("\nsend B to first channel")
intOb1.on(.Next("B"))
print("now that both channels are full, whenever either channel emits a value, the combined channel also emits a value")
print("\nsend 2 to second channel")
intOb2.on(.Next(2))
print("note that the combined channel emits a value whenever either sub-channel emits a value, even if the value is the same")
}
//: This example show once in each channel there are output for each new channel output the resulting observable also produces an output
//: To produce output, at least one element has to be received from each sequence in arguements.
example("combineLatest 2nd") {
example("combineLatest 2") {
let intOb1 = just(2)
let intOb2 = sequenceOf(0, 1, 2, 3, 4)
combineLatest(intOb1, intOb2) {
$0 * $1
}
.subscribeNext { (x: Int) in
print(x)
.subscribe {
print($0)
}
}
/*:
Rx has a group of `combineLatest` functions.
The next sample demonstrates `combineLatest` with three arguments.
*/
example("combineLatest 3rd") {
//: Combine latest has versions with more then 2 arguments.
example("combineLatest 3") {
let intOb1 = just(2)
let intOb2 = sequenceOf(0, 1, 2, 3)
let intOb3 = sequenceOf(0, 1, 2, 3, 4)
@ -98,8 +88,8 @@ example("combineLatest 3rd") {
combineLatest(intOb1, intOb2, intOb3) {
($0 + $1) * $2
}
.subscribeNext { (x: Int) in
print(x)
.subscribe {
print($0)
}
}
@ -108,48 +98,36 @@ example("combineLatest 3rd") {
/*:
### `zip`
Takes several source Observables and a closure as parameters, returns an Observable which emit the items of the second Obsevable procesed, through the closure, with the last item of first Observable
The Observable returned by `zip` emits an item only when all of the imputs Observables have emited an item
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 1st") {
example("zip 1") {
let intOb1 = PublishSubject<String>()
let intOb2 = PublishSubject<Int>()
zip(intOb1, intOb2) {
"\($0) \($1)"
}
.subscribeNext { (x: String) in
print(x)
.subscribe {
print($0)
}
print("send A to first channel")
sendNext(intOb1, "A")
print("note that nothing outputs")
intOb1.on(.Next("A"))
print("\nsend 1 to second channel")
sendNext(intOb2, 1)
print("now that both source channels have output, there is output")
intOb2.on(.Next(1))
print("\nsend B to first channel")
sendNext(intOb1, "B")
print("note that nothing outputs, since channel 1 has two outputs but channel 2 only has one")
intOb1.on(.Next("B"))
print("\nsend C to first channel")
sendNext(intOb1, "C")
print("note that nothing outputs, it is the same as in the previous step, since channel 1 has three outputs but channel 2 only has one")
intOb1.on(.Next("C"))
print("\nsend 2 to second channel")
sendNext(intOb2, 2)
print("note that the combined channel emits a value with the second output of each channel")
intOb2.on(.Next(2))
}
//: This example show once in each channel there are output for each new channel output the resulting observable also produces an output
example("zip 2nd") {
example("zip 2") {
let intOb1 = just(2)
let intOb2 = sequenceOf(0, 1, 2, 3, 4)
@ -157,25 +135,22 @@ example("zip 2nd") {
zip(intOb1, intOb2) {
$0 * $1
}
.subscribeNext { (x: Int) in
print(x)
.subscribe {
print($0)
}
}
/*:
Demostrates simple usage of `zip` operator.
*/
example("zip 3rd") {
example("zip 3") {
let intOb1 = sequenceOf(0, 1)
let intOb2 = sequenceOf(0, 1, 2, 3)
let intOb3 = sequenceOf(0, 1, 2, 3, 4)
zip(intOb1, intOb2, intOb3) {
($0 + $1) * $2
($0 + $1) * $2
}
.subscribeNext { (x: Int) in
print(x)
.subscribe {
print($0)
}
}
@ -185,13 +160,13 @@ example("zip 3rd") {
/*:
### `merge`
Combine multiple Observables, of the same type, into one by merging their emissions
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 1st") {
example("merge 1") {
let subject1 = PublishSubject<Int>()
let subject2 = PublishSubject<Int>()
@ -201,33 +176,33 @@ example("merge 1st") {
print(int)
}
sendNext(subject1, 20)
sendNext(subject1, 40)
sendNext(subject1, 60)
sendNext(subject2, 1)
sendNext(subject1, 80)
sendNext(subject1, 100)
sendNext(subject2, 1)
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 2nd") {
example("merge 2") {
let subject1 = PublishSubject<Int>()
let subject2 = PublishSubject<Int>()
sequenceOf(subject1, subject2)
.merge(maxConcurrent: 2)
.subscribeNext { int in
print(int)
.subscribe {
print($0)
}
sendNext(subject1, 20)
sendNext(subject1, 40)
sendNext(subject1, 60)
sendNext(subject2, 1)
sendNext(subject1, 80)
sendNext(subject1, 100)
sendNext(subject2, 1)
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))
}
@ -235,7 +210,7 @@ example("merge 2nd") {
/*:
### `switchLatest`
Convert an Observable that emits Observables into a single Observable that emits the items emitted by the most-recently-emitted of those Observables.
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)
@ -251,8 +226,8 @@ example("switchLatest") {
let d = var3
.switchLatest()
.subscribeNext { (e: Int) -> Void in
print("\(e)")
.subscribe {
print($0)
}
var1.sendNext(1)
@ -264,7 +239,6 @@ example("switchLatest") {
var2.sendNext(201)
print("var1 isn't observed anymore")
var1.sendNext(5)
var1.sendNext(6)
var1.sendNext(7)

View File

@ -8,8 +8,9 @@ import RxSwift
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.
@ -19,23 +20,23 @@ Discard any items emitted by an Observable after a second Observable emits an it
*/
example("takeUntil") {
let observable1 = PublishSubject<Int>()
let observable2 = PublishSubject<Int>()
let originalSequence = PublishSubject<Int>()
let whenThisSendsNextWorldStops = PublishSubject<Int>()
observable1
.takeUntil(observable2)
.subscribeNext { int in
print(int)
}
originalSequence
.takeUntil(whenThisSendsNextWorldStops)
.subscribe {
print($0)
}
sendNext(observable1, 1)
sendNext(observable1, 2)
sendNext(observable1, 3)
sendNext(observable1, 4)
originalSequence.on(.Next(1))
originalSequence.on(.Next(2))
originalSequence.on(.Next(3))
originalSequence.on(.Next(4))
sendNext(observable2, 1)
whenThisSendsNextWorldStops.on(.Next(1))
sendNext(observable1, 5)
originalSequence.on(.Next(5))
}
@ -50,21 +51,21 @@ Mirror items emitted by an Observable until a specified condition becomes false
*/
example("takeWhile") {
let observable1 = PublishSubject<Int>()
let sequence = PublishSubject<Int>()
observable1
sequence
.takeWhile { int in
int < 4
}
.subscribeNext { int in
print(int)
}
.subscribe {
print($0)
}
sendNext(observable1, 1)
sendNext(observable1, 2)
sendNext(observable1, 3)
sendNext(observable1, 4)
sendNext(observable1, 5)
sequence.on(.Next(1))
sequence.on(.Next(2))
sequence.on(.Next(3))
sequence.on(.Next(4))
sequence.on(.Next(5))
}

View File

@ -16,15 +16,15 @@ func sampleWithoutConnectableOperators() {
let int1 = interval(1, MainScheduler.sharedInstance)
int1
.subscribeNext {
.subscribe {
print("first subscription \($0)")
}
delay(5) {
int1
.subscribeNext {
.subscribe {
print("second subscription \($0)")
}
}
}
}
@ -45,17 +45,17 @@ func sampleWithMulticast() {
let subject1 = PublishSubject<Int64>()
subject1
.subscribeNext {
.subscribe {
print("Subject \($0)")
}
}
let int1 = interval(1, MainScheduler.sharedInstance)
.multicast(subject1)
int1
.subscribeNext {
.subscribe {
print("first subscription \($0)")
}
}
delay(2) {
int1.connect()
@ -63,25 +63,21 @@ func sampleWithMulticast() {
delay(4) {
int1
.subscribeNext {
.subscribe {
print("second subscription \($0)")
print("---")
}
}
}
delay(6) {
int1
.subscribeNext {
print("thirth subscription \($0)")
}
.subscribe {
print("third subscription \($0)")
}
}
}
//sampleWithMulticast()
// sampleWithMulticast()
/*:
@ -100,7 +96,7 @@ func sampleWithReplayBuffer0() {
.replay(0)
int1
.subscribeNext {
.subscribe {
print("first subscription \($0)")
}
@ -110,22 +106,21 @@ func sampleWithReplayBuffer0() {
delay(4) {
int1
.subscribeNext {
.subscribe {
print("second subscription \($0)")
print("---")
}
}
}
delay(6) {
int1
.subscribeNext {
print("thirth subscription \($0)")
}
.subscribe {
print("third subscription \($0)")
}
}
}
//sampleWithReplayBuffer0()
// sampleWithReplayBuffer0()
func sampleWithReplayBuffer2() {
@ -136,7 +131,7 @@ func sampleWithReplayBuffer2() {
.replay(2)
int1
.subscribeNext {
.subscribe {
print("first subscription \($0)")
}
@ -146,25 +141,21 @@ func sampleWithReplayBuffer2() {
delay(4) {
int1
.subscribeNext {
.subscribe {
print("second subscription \($0)")
print("---")
}
}
delay(6) {
int1
.subscribeNext {
.subscribe {
print("third subscription \($0)")
}
}
}
//sampleWithReplayBuffer2()
// sampleWithReplayBuffer2()
/*:
@ -183,7 +174,7 @@ func sampleWithPublish() {
.publish()
int1
.subscribeNext {
.subscribe {
print("first subscription \($0)")
}
@ -193,21 +184,22 @@ func sampleWithPublish() {
delay(4) {
int1
.subscribeNext {
.subscribe {
print("second subscription \($0)")
print("---")
}
}
}
delay(6) {
int1
.subscribeNext {
.subscribe {
print("third subscription \($0)")
}
}
}
}
// sampleWithPublish()
XCPSetExecutionShouldContinueIndefinitely(true)
//: [Index](Index)

View File

@ -1,235 +0,0 @@
//: [<< Previous](@previous) - [Index](Index)
import RxSwift
import Foundation
/*:
## Creating observables
Operators that originate new Observables.
### `empty`
Creates an observable that contains no objects. The only message it sends is the `.Completed` message.
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/empty.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/empty-never-throw.html )
*/
example("Empty observable") {
let emptyObservable: Observable<Int> = empty()
let emptySubscriber = emptyObservable .subscribe { event in
switch event {
case .Next(let box):
print("\(box.value)")
case .Completed:
print("completed")
case .Error(let error):
print("\(error)")
}
}
}
/*:
As you can see, no values are ever sent to the subscriber of an empty observable. It just completes and is done.
### `never`
Creates an observable that contains no objects and never completes or errors out.
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/never.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/empty-never-throw.html )
*/
example("Never observable") {
let neverObservable: Observable<String> = never()
let neverSubscriber = neverObservable
.subscribe { _ in
print("This block is never called.")
}
}
/*:
### `failWith` a.k.a `throw`
Creates an observable that contains no objects and send only a error out.
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/throw.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/empty-never-throw.html )
*/
example("failWith") {
let error = NSError(domain: "Test", code: -1, userInfo: nil)
let errorObservable: Observable<Int> = failWith(error)
let errorSubscriber = errorObservable
.subscribe { event in
switch event {
case .Next(let box):
print("\(box.value)")
case .Completed:
print("completed")
case .Error(let error):
print("\(error)")
}
}
}
/*:
### `returnElement` / `just`
These two functions behave identically. They send two messages to subscribers. The first message is the value and the second message is `.Complete`.
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/just.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/just.html )
*/
example("returnElement/just") {
let oneObservable = just(32)
let oneObservableSubscriber = oneObservable
.subscribe { event in
switch event {
case .Next(let box):
print("\(box.value)")
case .Completed:
print("completed")
case .Error(let error):
print("\(error)")
}
}
}
/*:
Here we see that the `.Next` event is sent just once, then the `.Completed` event is sent.
### `sequenceOf`
Now we are getting to some more interesting ways to create an Observable. This function creates an observable that produces a number of values before completing.
*/
example("sequenceOf") {
let multipleObservable/* : Observable<Int> */ = sequenceOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
let multipleObservableSubscriber = multipleObservable
.subscribe { event in
switch event {
case .Next(let box):
print("\(box.value)")
case .Completed:
print("completed")
case .Error(let error):
print("\(error)")
}
}
}
/*:
With the above, you will see that the `.Next` event was sent ten times, once for each element. Then `.Complete` was sent.
### `from`
We can also create an observable from any SequenceType, such as an array.
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/from.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/from.html )
*/
example("from") {
let fromArrayObservable = from([1, 2, 3, 4, 5])
let fromArrayObservableSubscriber = fromArrayObservable
.subscribe { event in
switch event {
case .Next(let box):
print("\(box.value)")
case .Completed:
print("completed")
case .Error(let error):
print("\(error)")
}
}
}
/*:
### `create`
Create an Observable from scratch by means of a function
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/create.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/create.html )
*/
example("create") {
print("creating")
let observable: Observable<Int> = create { observer in
print("emmiting")
sendNext(observer, 0)
sendNext(observer, 1)
sendNext(observer, 2)
return AnonymousDisposable {}
}
observable
.subscribeNext {
print($0)
}
observable
.subscribeNext {
print($0)
}
}
/*:
### `deferred`
Create an Observable from a function which create an observable. But 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> = deferred {
print("creating")
return create { observer in
print("emmiting")
sendNext(observer, 0)
sendNext(observer, 1)
sendNext(observer, 2)
return AnonymousDisposable {}
}
}
deferredSequence
.subscribeNext {
print($0)
}
deferredSequence
.subscribeNext {
print($0)
}
}
//: [Index](Index) - [Next >>](@next)

View File

@ -11,66 +11,46 @@ Operators that help to recover from error notifications from an Observable.
/*:
### `catchError`
Recover from an onError notification by continuing the sequence without error
Recover from an `Error` notification by continuing the sequence without error
![](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 1st") {
let observable1 = PublishSubject<Int>()
let observable2 = PublishSubject<Int>()
example("catchError 1") {
let sequenceThatFails = PublishSubject<Int>()
let recoverySequence = sequenceOf(100, 200, 300, 400)
observable1
sequenceThatFails
.catchError { error in
return observable2
return recoverySequence
}
.subscribe { event in
switch event {
case .Next(let value):
print("\(value)")
case .Completed:
print("completed")
case .Error(let error):
print("\(error)")
}
.subscribe {
print($0)
}
sendNext(observable1, 1)
sendNext(observable1, 2)
sendNext(observable1, 3)
sendNext(observable1, 4)
sendError(observable1, NSError(domain: "Test", code: 0, userInfo: nil))
sendNext(observable2, 100)
sendNext(observable2, 200)
sendNext(observable2, 300)
sendNext(observable2, 400)
sendCompleted(observable2)
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)))
}
example("catchError 2nd") {
let observable1 = PublishSubject<Int>()
example("catchError 2") {
let sequenceThatFails = PublishSubject<Int>()
observable1
sequenceThatFails
.catchErrorResumeNext(100)
.subscribe { event in
switch event {
case .Next(let value):
print("\(value)")
case .Completed:
print("completed")
case .Error(let error):
print("\(error)")
}
.subscribe {
print($0)
}
sendNext(observable1, 1)
sendNext(observable1, 2)
sendNext(observable1, 3)
sendNext(observable1, 4)
sendError(observable1, NSError(domain: "Test", code: 0, userInfo: nil))
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)))
}
@ -86,34 +66,27 @@ If a source Observable emits an error, resubscribe to it in the hopes that it wi
*/
example("retry") {
var count = 1 // bad practice, only for example purposes
let observable: Observable<Int> = create { observer in
let funnyLookingSequence: Observable<Int> = create { observer in
let error = NSError(domain: "Test", code: 0, userInfo: nil)
sendNext(observer, 0)
sendNext(observer, 1)
sendNext(observer, 2)
observer.on(.Next(0))
observer.on(.Next(1))
observer.on(.Next(2))
if count < 2 {
sendError(observer, error)
observer.on(.Error(error))
count++
}
sendNext(observer, 3)
sendNext(observer, 4)
sendNext(observer, 5)
sendCompleted(observer)
observer.on(.Next(3))
observer.on(.Next(4))
observer.on(.Next(5))
observer.on(.Completed)
return AnonymousDisposable {}
return NopDisposable.instance
}
observable
funnyLookingSequence
.retry()
.subscribe { event in
switch event {
case .Next(let value):
print("\(value)")
case .Completed:
print("completed")
case .Error(let error):
print("\(error)")
}
.subscribe {
print($0)
}
}

View File

@ -6,10 +6,10 @@ import RxSwift
## Filtering Observables
Operators that selectively emit items from a source Observable.
*/
### `where` / `filter`
/*:
### `filter`
Emit only those items from an Observable that pass a predicate test
@ -19,12 +19,12 @@ Emit only those items from an Observable that pass a predicate test
*/
example("filter") {
let onlyEvensSubscriber = sequenceOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
let subscription = sequenceOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
.filter {
$0 % 2 == 0
}
.subscribeNext { value in
print("\(value)")
.subscribe {
print($0)
}
}
@ -39,10 +39,10 @@ Suppress duplicate items emitted by an Observable
[More info in reactive.io website]( http://reactivex.io/documentation/operators/distinct.html )
*/
example("distinctUntilChanged") {
let distinctUntilChangedSubscriber = sequenceOf(1, 2, 3, 1, 1, 4)
let subscription = sequenceOf(1, 2, 3, 1, 1, 4)
.distinctUntilChanged()
.subscribeNext { value in
print("\(value)")
.subscribe {
print($0)
}
}
@ -57,13 +57,13 @@ Emit only the first n items emitted by an Observable
[More info in reactive.io website]( http://reactivex.io/documentation/operators/take.html )
*/
example("take") {
let distinctUntilChangedSubscriber = sequenceOf(1, 2, 3, 4, 5, 6)
let subscription = sequenceOf(1, 2, 3, 4, 5, 6)
.take(3)
.subscribeNext { value in
print("\(value)")
.subscribe {
print($0)
}
}
//: [Index](Index) - [Next >>](@next)
//: [Index](Index) - [Next >>](@next)

View File

@ -12,16 +12,15 @@
## Index:
1. [Introduction](Introduction)
2. [Subjects](Subjects)
3. [Creating observables](Creating_observables)
4. [Transforming Observables](Transforming_Observables)
5. [Filtering Observables](Filtering_Observables)
6. [Combining Observables](Combining_Observables)
7. [Error Handling Operators](Error_Handling_Operators)
8. [Observable Utility Operators](Observable_Utility_Operators)
9. [Conditional and Boolean Operators](Conditional_and_Boolean_Operators)
10. [Mathematical and Aggregate Operators](Mathematical_and_Aggregate_Operators)
11. [Connectable Observable Operators](Connectable_Observable_Operators)
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)
*/

View File

@ -1,6 +1,7 @@
//: [<< Index](@previous)
import RxSwift
import Foundation
/*:
# Introduction
@ -20,190 +21,151 @@ Creating an Observable is one thing, but if nothing subscribes to the observable
/*:
### empty
`empty` creates an observable that contains no objects. The only message it sends is the `.Completed` message.
`empty` creates an empty sequence. The only message it sends is the `.Completed` message.
*/
example("Empty observable") {
let emptyObservable: Observable<Int> = empty()
example("empty") {
let emptySequence: Observable<Int> = empty()
let emptySubscriber = emptyObservable .subscribe { event in
switch event {
case .Next(let box):
print("\(box.value)")
case .Completed:
print("completed")
case .Error(let error):
print("\(error)")
let subscription = emptySequence
.subscribe { event in
print(event)
}
}
}
/*:
As you can see, no values are ever sent to the subscriber of an empty observable. It just completes and is done.
*/
/*:
### never
`never` creates an observable that contains no objects and never completes or errors out.
`never` creates a sequence that never sends any element or completes.
*/
example("Never observable") {
let neverObservable: Observable<String> = never()
example("never") {
let neverSequence: Observable<String> = never()
let neverSubscriber = neverObservable .subscribe { _ in
print("This block is never called.")
}
}
/*:
### returnElement/just
These two functions behave identically. They send two messages to subscribers. The first message is the value and the second message is `.Complete`.
*/
example("returnElement/just") {
let oneObservable = just(32)
let oneObservableSubscriber = oneObservable
.subscribe { event in
switch event {
case .Next(let box):
print("\(box.value)")
case .Completed:
print("completed")
case .Error(let error):
print("\(error)")
}
let subscription = neverSequence
.subscribe { _ in
print("This block is never called.")
}
}
/*:
Here we see that the `.Next` event is sent just once, then the `.Completed` event is sent.
### 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 = just(32)
let subscription = singleElementSequence
.subscribe { event in
print(event)
}
}
/*:
### sequence
Now we are getting to some more interesting ways to create an Observable. This function creates an observable that produces a number of values before completing.
### sequenceOf
`sequenceOf` creates a sequence of a fixed number of elements.
*/
example("sequence") {
let multipleObservable/* : Observable<Int> */ = sequenceOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
example("sequenceOf") {
let sequenceOfElements/* : Observable<Int> */ = sequenceOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
let multipleObservableSubscriber = multipleObservable
let subscription = sequenceOfElements
.subscribe { event in
switch event {
case .Next(let box):
print("\(box.value)")
case .Completed:
print("completed")
case .Error(let error):
print("\(error)")
}
print(event)
}
}
/*:
With the above, you will see that the `.Next` event was sent ten times, once for each element. Then `.Complete` was sent.
*/
/*:
### from
We can also create an observable from any SequenceType, such as an array
`from` creates a sequence from `SequenceType`
*/
example("from") {
let fromArrayObservable = from([1, 2, 3, 4, 5])
let sequenceFromArray = from([1, 2, 3, 4, 5])
let fromArrayObservableSubscriber = fromArrayObservable
let subscription = sequenceFromArray
.subscribe { event in
switch event {
case .Next(let box):
print("\(box.value)")
case .Completed:
print("completed")
case .Error(let error):
print("\(error)")
}
print(event)
}
}
/*:
Now these functions are all well and good, but the really useful ones are in the RxCocoa library.
`rx_observe` exist on every NSObject and wraps KVO.
`rx_tap` exists on buttons and wraps @IBActions
`rx_notification` wraps NotificationCenter events
... and so on.
Take some time and search for code matching `-> Observable` in the RxCocoa framework to get a sense of how every action can be modeled as an observable. You can even create your own functions that make Observable objects.
## Subscribing
Up to this point, I have only used the `subscribe` method to listen to Observables, but there are several others.
### create
`create` creates sequence using Swift closure. This examples creates custom version of `just` operator.
*/
example("subscribeNext") {
let nextOnlySubscriber = sequenceOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
.subscribeNext { value in
print("\(value)")
example("create") {
let myJust = { (singleElement: Int) -> Observable<Int> in
return create { observer in
observer.on(.Next(singleElement))
observer.on(.Completed)
return NopDisposable.instance
}
}
let subscription = myJust(5)
.subscribe { event in
print(event)
}
}
/*:
With the above we only interest ourselves in the values returned by the observable without regard to whether/when it completes or errors. Many of the observables that we use have an indefinite lifespan. There is also `subscribeCompleted` and `subscribeError` for when you are looking for when an observable will stop sending.
Also note that you can have multiple subscribers following to the same observable (as I did in the example above.) All the subscribers will be notified when an event occurs.
### failWith
create an Observable that emits no items and terminates with an error
*/
/*:
## Reducing a sequence
Now that you understand how to create Observables and subscribe to them. Let's look at the various ways we can manipulate an observable sequence. First lets examine ways to reduce a sequence into fewer events.
### where/filter
The most common way to reduce a sequence is to apply a filter to it and the most generic of these is `where` or `filter`. You will see in the code below that the messages containing odd numbers are being removed so the subscriber wont see them.
*/
example("filter") {
let onlyEvensSubscriber = sequenceOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
.filter {
$0 % 2 == 0
}
.subscribeNext { value in
print("\(value)")
example("failWith") {
let error = NSError(domain: "Test", code: -1, userInfo: nil)
let erroredSequence: Observable<Int> = failWith(error)
let subscription = erroredSequence
.subscribe { event in
print(event)
}
}
/*:
### distinctUntilChanged
This filter tracks the last value emitted and removes like values. This function is good for reducing noise in a sequence.
*/
### `deferred`
example("distinctUntilChanged") {
let distinctUntilChangedSubscriber = sequenceOf(1, 2, 3, 1, 1, 4)
.distinctUntilChanged()
.subscribeNext { value in
print("\(value)")
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> = deferred {
print("creating")
return 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)
}
}
/*:
In the example above, the values 1, 2, 3, 1, 4 will be printed. The extra 1 will be filtered out.
There are several different versions of `distinctUntilChanged`. Have a look in the file Observable+Single.swift to review them.
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
*/
/*:
## Reducing a sequence
### `reduce`
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.
*/
example("reduce") {
let aggregateSubscriber = sequenceOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
.reduce(0, +)
.subscribeNext { value in
print("\(value)")
}
}
//: [Index](Index) - [Next >>](@next)

View File

@ -7,8 +7,9 @@ import RxSwift
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.
@ -26,8 +27,8 @@ example("concat") {
let d = var3
.concat()
.subscribeNext { (e: Int) -> Void in
print("\(e)")
.subscribe {
print($0)
}
var1.on(.Next(1))
@ -64,10 +65,10 @@ This function will perform a function on each element in the sequence until it i
*/
example("reduce") {
let reduceSubscriber = sequenceOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
sequenceOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
.reduce(0, +)
.subscribeNext { value in
print("\(value)")
.subscribe {
print($0)
}
}

View File

@ -7,112 +7,107 @@ import Foundation
A toolbox of useful Operators for working with Observables.
*/
/*:
### `subscribe`
Create an Disposable which listen events from source Observable, the given closure take the Even and is responsible for the actions to perform when the it is produced.
[More info in reactive.io website]( http://reactivex.io/documentation/operators/subscribe.html )
*/
example("subscribe") {
let intOb1 = PublishSubject<Int>()
let sequenceOfInts = PublishSubject<Int>()
intOb1
.subscribe { event in
print(event)
sequenceOfInts
.subscribe {
print($0)
}
sendNext(intOb1, 1)
sendCompleted(intOb1)
sequenceOfInts.on(.Next(1))
sequenceOfInts.on(.Completed)
}
/*:
There are several variants of the `subscribe` operator. They works over one posible event type:
There are several variants of the `subscribe` operator.
*/
/*:
### `subscribeNext`
Create an Disposable which listen only Next event from source Observable, the given closure take the Even's value and is responsible for the actions to perform only when the Next even is produced.
*/
example("subscribeNext") {
let intOb1 = PublishSubject<Int>()
let sequenceOfInts = PublishSubject<Int>()
intOb1
.subscribeNext { int in
print(int)
sequenceOfInts
.subscribeNext {
print($0)
}
sendNext(intOb1, 1)
sendCompleted(intOb1)
sequenceOfInts.on(.Next(1))
sequenceOfInts.on(.Completed)
}
/*:
### `subscribeCompleted`
Create an Disposable which listen only Completed event from source Observable, the given closure take the Even's value and is responsible for the actions to perform only when the Completed even is produced.
*/
example("subscribeCompleted") {
let intOb1 = PublishSubject<Int>()
let sequenceOfInts = PublishSubject<Int>()
intOb1
sequenceOfInts
.subscribeCompleted {
print("It's completed")
}
sendNext(intOb1, 1)
sendCompleted(intOb1)
sequenceOfInts.on(.Next(1))
sequenceOfInts.on(.Completed)
}
/*:
### `subscribeError
### `subscribeError`
Create an Disposable which listen only Error event from source Observable, the given closure take the Even's value and is responsible for the actions to perform only when the Error even is produced
*/
example("subscribeError") {
let intOb1 = PublishSubject<Int>()
let sequenceOfInts = PublishSubject<Int>()
intOb1
sequenceOfInts
.subscribeError { error in
print(error)
}
sendNext(intOb1, 1)
sendError(intOb1, NSError(domain: "Examples", code: -1, userInfo: nil))
sequenceOfInts.on(.Next(1))
sequenceOfInts.on(.Error(NSError(domain: "Examples", code: -1, userInfo: nil)))
}
/*:
### `doOn`
Returns the same source Observable but the given closure responsible for the actions to perform when the even is produced. The gived closure obtain the event produced by the source observable
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 intOb1 = PublishSubject<Int>()
let sequenceOfInts = PublishSubject<Int>()
let intOb2 = intOb1
.doOn { event in
print("first \(event)")
sequenceOfInts
.doOn {
print("Intercepted event \($0)")
}
intOb2
.subscribeNext { int in
print("second \(int)")
.subscribe {
print($0)
}
sendNext(intOb1, 1)
sequenceOfInts.on(.Next(1))
sequenceOfInts.on(.Completed)
}
//: [Index](Index) - [Next >>](@next)

View File

@ -2,10 +2,15 @@
import RxSwift
func writeSequenceToConsole(name: String, sequence: Observable<String>) {
/*:
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) {
sequence
.subscribeNext {
print("Subscription: \(name), value: \($0)")
.subscribe { e in
print("Subscription: \(name), event: \(e)")
}
}
@ -14,7 +19,7 @@ func writeSequenceToConsole(name: String, sequence: Observable<String>) {
## PublishSubject
PublishSubject can begin emitting items immediately upon creation, but there is a risk that one or more items may be lost between the time the Subject is created and the observer subscribes to it.
`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)
@ -24,11 +29,11 @@ PublishSubject can begin emitting items immediately upon creation, but there is
example("PublishSubject") {
let subject = PublishSubject<String>()
writeSequenceToConsole("1", sequence: subject)
sendNext(subject, "a")
sendNext(subject, "b")
subject.on(.Next("a"))
subject.on(.Next("b"))
writeSequenceToConsole("2", sequence: subject)
sendNext(subject, "c")
sendNext(subject, "d")
subject.on(.Next("c"))
subject.on(.Next("d"))
}
@ -36,23 +41,25 @@ example("PublishSubject") {
## ReplaySubject
ReplaySubject emits to any observer all of the items, in the buffer, that were emitted by the source
`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 subject = ReplaySubject<String>.create(bufferSize: 1)
writeSequenceToConsole("1", sequence: subject)
sendNext(subject, "a")
sendNext(subject, "b")
subject.on(.Next("a"))
subject.on(.Next("b"))
writeSequenceToConsole("2", sequence: subject)
sendNext(subject, "c")
sendNext(subject, "d")
subject.on(.Next("c"))
subject.on(.Next("d"))
}
/*:
## BehaviorSubject a.k.a. Variable
## 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).
@ -63,12 +70,29 @@ When an observer subscribes to a `BehaviorSubject`, it begins by emitting the it
example("BehaviorSubject") {
let subject = BehaviorSubject(value: "z")
writeSequenceToConsole("1", sequence: subject)
sendNext(subject, "a")
sendNext(subject, "b")
subject.on(.Next("a"))
subject.on(.Next("b"))
writeSequenceToConsole("2", sequence: subject)
sendNext(subject, "c")
sendNext(subject, "d")
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 variable = Variable("z")
writeSequenceToConsole("1", sequence: variable)
variable.sendNext("a")
variable.sendNext("b")
writeSequenceToConsole("2", sequence: variable)
variable.sendNext("c")
variable.sendNext("d")
}
//: [Index](Index) - [Next >>](@next)

View File

@ -6,8 +6,9 @@ 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
@ -18,21 +19,13 @@ Transform the items emitted by an Observable by applying a function to each item
*/
example("map") {
let observable1: Observable<Character> = create { observer in
sendNext(observer, Character("A"))
sendNext(observer, Character("B"))
sendNext(observer, Character("C"))
let originalSequence = sequenceOf(Character("A"), Character("B"), Character("C"))
return AnonymousDisposable {}
}
observable1
originalSequence
.map { char in
char.hashValue
}
.subscribeNext { int in
print(int)
}
.subscribe { print($0) }
}
@ -46,32 +39,17 @@ Transform the items emitted by an Observable into Observables, then flatten the
[More info in reactive.io website]( http://reactivex.io/documentation/operators/flatmap.html )
*/
example("flatMap") {
let observable1: Observable<Int> = create { observer in
sendNext(observer, 1)
sendNext(observer, 2)
sendNext(observer, 3)
let sequenceInt = sequenceOf(1, 2, 3)
return AnonymousDisposable {}
}
let sequenceString = sequenceOf("A", "B", "C", "D", "E", "F", "--")
let observable2: Observable<String> = create { observer in
sendNext(observer, "A")
sendNext(observer, "B")
sendNext(observer, "C")
sendNext(observer, "D")
sendNext(observer, "F")
sendNext(observer, "--")
return AnonymousDisposable {}
}
observable1
sequenceInt
.flatMap { int in
observable2
sequenceString
}
.subscribeNext {
.subscribe {
print($0)
}
}
}
@ -85,24 +63,15 @@ Apply a function to each item emitted by an Observable, sequentially, and emit e
[More info in reactive.io website]( http://reactivex.io/documentation/operators/scan.html )
*/
example("scan") {
let observable: Observable<Int> = create { observer in
sendNext(observer, 0)
sendNext(observer, 1)
sendNext(observer, 2)
sendNext(observer, 3)
sendNext(observer, 4)
sendNext(observer, 5)
let sequenceToSum = sequenceOf(0, 1, 2, 3, 4, 5)
return AnonymousDisposable {}
}
observable
sequenceToSum
.scan(0) { acum, elem in
acum + elem
}
.subscribeNext {
.subscribe {
print($0)
}
}
}

View File

@ -4,7 +4,6 @@
<page name='Index'/>
<page name='Introduction'/>
<page name='Subjects'/>
<page name='Creating_observables'/>
<page name='Transforming_Observables'/>
<page name='Filtering_Observables'/>
<page name='Combining_Observables'/>