improve playgrouds

Thanks @finneycanhelp for help me to improve my English writing
This commit is contained in:
Carlos García 2016-05-07 13:32:09 +02:00 committed by Krunoslav Zaher
parent cf0ef0b941
commit 207761c2a7
12 changed files with 719 additions and 456 deletions

View File

@ -29,11 +29,10 @@ emit a specified sequence of items before beginning to emit the items from the s
*/
example("startWith") {
let subscription = Observable.of(4, 5, 6, 7, 8, 9)
.startWith(3)
.startWith(2)
.startWith(1)
.startWith(0)
let subscription = Observable.of("🐶","🐱","🐭","🐹")
.startWith("🔴")
.startWith("🅱️")
.startWith("🆎")
.subscribe {
print($0)
}
@ -51,34 +50,34 @@ when an item is emitted by either of two Observables, combine the latest item em
*/
example("combineLatest 1") {
let intOb1 = PublishSubject<String>()
let intOb2 = PublishSubject<Int>()
_ = Observable.combineLatest(intOb1, intOb2) {
let stringObs = PublishSubject<String>()
let intObs = PublishSubject<Int>()
_ = Observable.combineLatest(stringObs, intObs) {
"\($0) \($1)"
}
.subscribe {
print($0)
}
intOb1.on(.Next("A"))
intOb2.on(.Next(1))
intOb1.on(.Next("B"))
intOb2.on(.Next(2))
stringObs.on(.Next("🅰️"))
intObs.on(.Next(1))
stringObs.on(.Next("🅱️"))
intObs.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
let stringObs = Observable.of("🐶","🐱","🐭","🐹")
let intObs = Observable.just(2)
_ = Observable.combineLatest(stringObs, intObs) {
"\($0) \($1)"
}
.subscribe {
print($0)
@ -90,12 +89,12 @@ example("combineLatest 2") {
//: 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
let intObs = Observable.just(2)
let stringObs1 = Observable.of("🐶","🐱","🐭","🐹")
let stringObs2 = Observable.of("🅰️","🅱️","🆎")
_ = Observable.combineLatest(intObs, stringObs1, stringObs2) {
"\($0) \($1) \($2)"
}
.subscribe {
print($0)
@ -107,15 +106,15 @@ example("combineLatest 3") {
//: Combinelatest version that allows combining sequences with different types.
example("combineLatest 4") {
let intOb = Observable.just(2)
let stringOb = Observable.just("a")
let intObs = Observable.just(2)
let stringObs = Observable.just("🔴")
_ = Observable.combineLatest(intOb, stringOb) {
"\($0) " + $1
_ = Observable.combineLatest(intObs, stringObs) {
"\($0) " + $1
}
.subscribe {
print($0)
}
}
}
@ -123,14 +122,14 @@ example("combineLatest 4") {
//: 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)
let stringObs1 = Observable.just("❤️")
let stringObs2 = Observable.of("🐶","🐱","🐭","🐹")
let stringObs3 = Observable.of("🅰️","🅱️","🆎")
_ = [intOb1, intOb2, intOb3].combineLatest { intArray -> Int in
Int((intArray[0] + intArray[1]) * intArray[2])
_ = [stringObs1, stringObs2, stringObs3].combineLatest { stringArray -> String in
stringArray[0] + stringArray[1] + stringArray[2]
}
.subscribe { (event: Event<Int>) -> Void in
.subscribe { (event: Event<String>) -> Void in
print(event)
}
}
@ -147,35 +146,34 @@ combine the emissions of multiple Observables together via a specified function
[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) {
let stringObs = PublishSubject<String>()
let intObs = PublishSubject<Int>()
_ = Observable.zip(stringObs, intObs) {
"\($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))
stringObs.on(.Next("🔴"))
intObs.on(.Next(1))
stringObs.on(.Next("🔵"))
stringObs.on(.Next("⚪️"))
intObs.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
let intObs = Observable.just(1)
let stringObs = Observable.of("🐶","🐱","🐭","🐹")
_ = Observable.zip(intObs, stringObs) {
"\($0) \($1)"
}
.subscribe {
print($0)
@ -184,12 +182,12 @@ example("zip 2") {
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
let intObs = Observable.of(1,2)
let stringObs1 = Observable.of("🐶","🐱","🐭","🐹")
let stringObs2 = Observable.of("🍎","🍐","🍊","🍋","🍉","🍓")
_ = Observable.zip(intObs, stringObs1, stringObs2) {
"\($0) \($1) \($2)"
}
.subscribe {
print($0)
@ -209,42 +207,42 @@ combine multiple Observables into one by merging their emissions
[More info in reactive.io website]( http://reactivex.io/documentation/operators/merge.html )
*/
example("merge 1") {
let subject1 = PublishSubject<Int>()
let subject2 = PublishSubject<Int>()
let subject1 = PublishSubject<String>()
let subject2 = PublishSubject<String>()
_ = Observable.of(subject1, subject2)
.merge()
.subscribeNext { int in
print(int)
.subscribeNext { string in
print(string)
}
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))
subject1.on(.Next("🍎"))
subject1.on(.Next("🍐"))
subject1.on(.Next("🍊"))
subject2.on(.Next("🔴"))
subject1.on(.Next("🍋"))
subject1.on(.Next("🍉"))
subject2.on(.Next("🔵"))
}
example("merge 2") {
let subject1 = PublishSubject<Int>()
let subject2 = PublishSubject<Int>()
let subject1 = PublishSubject<String>()
let subject2 = PublishSubject<String>()
_ = 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))
subject1.on(.Next("🍎"))
subject1.on(.Next("🍐"))
subject1.on(.Next("🍊"))
subject2.on(.Next("🔴"))
subject1.on(.Next("🍋"))
subject1.on(.Next("🍉"))
subject2.on(.Next("🔵"))
}
@ -259,32 +257,33 @@ convert an Observable that emits Observables into a single Observable that emits
[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 var1 = Variable("⚽️")
let var2 = Variable("🍎")
// var3 is an Observable<Observable<String>>
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
var1.value = "🏀"
var1.value = "🏈"
var1.value = "⚾️"
var1.value = "🎱"
var3.value = var2.asObservable()
var2.value = 201
var1.value = 5
var1.value = 6
var1.value = 7
var2.value = "🍐"
var1.value = "🏐"
var1.value = "🏉"
var2.value = "🍋"
}
//: [Index](Index) - [Next >>](@next)

View File

@ -78,5 +78,75 @@ example("takeWhile") {
}
/*:
### `skipWhile`
Discard items emitted by an Observable until a specified condition becomes false
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/skipWhile.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/skipwhile.html )
*/
example("skipWhile") {
let subscription = Observable.of(1, 2, 3, 4, 5, 6)
.skipWhile { integer -> Bool in
integer < 4
}
.subscribe {
print($0)
}
}
/*:
### `skipUntil`
Discard items emitted by an Observable until a second Observable emits an item
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/skipuntil.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/skipuntil.html )
*/
example("skipUntil") {
let ob1: Observable<Int> = Observable.create { observer -> Disposable in
observer.on(.Next(0))
delay(1) {
observer.on(.Next(1))
}
delay(2) {
observer.on(.Next(2))
}
delay(3) {
observer.on(.Next(3))
}
delay(4) {
observer.on(.Next(4))
}
delay(5) {
observer.on(.Completed)
}
return NopDisposable.instance
}
let ob2: Observable<String> = Observable.create { observer -> Disposable in
delay(2) {
observer.on(.Next("beginTakeItems"))
}
delay(6) {
observer.on(.Completed)
}
return NopDisposable.instance
}
let subscription = ob1
.skipUntil(ob2)
.subscribe {
print($0)
}
}
playgroundShouldContinueIndefinitely()
//: [Index](Index) - [Next >>](@next)

View File

@ -0,0 +1,229 @@
/*:
> # 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](Index) - [<< Previous](@previous)
import RxSwift
import Foundation
/*:
# Creating Observable sequences
There are a number of functions available to make Observables. In the rest of this page, we review several methods used to create Observable sequences.
### empty
`empty` creates an empty sequence. The only message it sends is the `.Completed` message.
*/
example("empty") {
let emptySequence/* : Observable<Int> */ = Observable<Int>.empty()
let subscription = emptySequence
.subscribe { event in
print(event)
}
}
/*:
### never
`never` creates a sequence that never sends any element or completes.
*/
example("never") {
let neverSequence/* : Observable<Int> */ = Observable<Int>.never()
let subscription = neverSequence
.subscribe { _ in
print("This block is never called.")
}
}
/*:
### just
`just` represents a sequence that contains just one element. It sends two messages to subscribers. The first message is the value of a single element and the second message is `.Completed`.
*/
example("just") {
let sequenceOfJustOneRedCircle/* : Observable<String> */ = Observable<String>.just("🔴")
let subscription = sequenceOfJustOneRedCircle
.subscribe { event in
print(event)
}
}
/*:
### sequenceOf
`sequenceOf` creates a sequence of a fixed number of elements.
*/
example("sequenceOf") {
let sequenceOfFourCircles/* : Observable<String> */ = Observable.of("🐶","🐱","🐭","🐹")
let subscription = sequenceOfFourCircles
.subscribe { event in
print(event)
}
}
/*:
### toObservable
`toObservable` creates a sequence out of an array.
*/
example("toObservable") {
let sequenceOfFourCircles/* : Observable<String> */ = ["🐶","🐱","🐭","🐹"].toObservable()
let subscription = sequenceOfFourCircles
.subscribe { event in
print(event)
}
}
/*:
### create
`create` creates sequence using a Swift closure. This examples creates a custom version of the `just` operator.
*/
example("create") {
let myJust = { (singleElement: String) -> Observable<String> in
return Observable.create { observer in
observer.on(.Next(singleElement))
observer.on(.Completed)
return NopDisposable.instance
}
}
let sequenceOfJustOneRedCircle/* : Observable<String> */ = myJust("🔴")
let subscription = sequenceOfJustOneRedCircle
.subscribe { event in
print(event)
}
}
/*:
### generate
`generate` creates a sequence that generates values for as long as the provided condition evaluates to `true`.
*/
example("generate") {
let generated/* : Observable<Int> */ = Observable.generate(
initialState: 0,
condition: { $0 < 3 },
iterate: { $0 + 1 }
)
let subscription = generated
.subscribe { event in
print(event)
}
}
/*:
### error
create an Observable that emits no items and immediately terminates with an error
*/
example("failWith") {
let error = NSError(domain: "Test", code: -1, userInfo: nil)
let erroredSequence/* : Observable<Int> */ = 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<String>.deferred {
print("creating")
return Observable.create { observer in
print("emmiting")
observer.on(.Next("🔴"))
observer.on(.Next("🐱"))
observer.on(.Next("🐵"))
return NopDisposable.instance
}
}
_ = deferredSequence
.subscribe { event in
print(event)
}
_ = deferredSequence
.subscribe { event in
print(event)
}
}
/*:
### range
create an Observable that emits a particular range of sequential integers
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/range.png)
*/
example("range") {
let rangeSequence/* : Observable<Int> */ = Observable.range(start: 3, count: 3)
let subscription = rangeSequence
.subscribe { event in
print(event)
}
}
/*:
### repeatElement
Create an Observable that emits a particular item multiple times
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/repeat.png)
*/
example("repeatElement") {
let repeatedSequence/* : Observable<String> */ = Observable.repeatElement("🔵", scheduler: MainScheduler.instance)
.take(5) // for example take can limit the number of repetitions
let subscription = repeatedSequence
.subscribe { event in
print(event)
}
}
playgroundShouldContinueIndefinitely()
/*:
There are many more useful methods in the RxCocoa library, so check them out:
* `rx_observe` exists on every NSObject and wraps KVO.
* `rx_tap` exists on buttons and wraps @IBActions
* `rx_notification` wraps NotificationCenter events
* ... and many others
*/
//: [Index](Index) - [Next >>](@next)

View File

@ -27,9 +27,9 @@ Recover from an `Error` notification by continuing the sequence without error
[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)
let sequenceThatFails = PublishSubject<String>()
let recoverySequence = Observable.of("🍎","🍐","🍊","🍋")
_ = sequenceThatFails
.catchError { error in
return recoverySequence
@ -37,28 +37,28 @@ example("catchError 1") {
.subscribe {
print($0)
}
sequenceThatFails.on(.Next(1))
sequenceThatFails.on(.Next(2))
sequenceThatFails.on(.Next(3))
sequenceThatFails.on(.Next(4))
sequenceThatFails.on(.Next("🔴"))
sequenceThatFails.on(.Next("🐱"))
sequenceThatFails.on(.Next("🐵"))
sequenceThatFails.on(.Next("🐷"))
sequenceThatFails.on(.Error(NSError(domain: "Test", code: 0, userInfo: nil)))
}
example("catchError 2") {
let sequenceThatFails = PublishSubject<Int>()
let sequenceThatFails = PublishSubject<String>()
_ = sequenceThatFails
.catchErrorJustReturn(100)
.catchErrorJustReturn("🍋")
.subscribe {
print($0)
}
sequenceThatFails.on(.Next(1))
sequenceThatFails.on(.Next(2))
sequenceThatFails.on(.Next(3))
sequenceThatFails.on(.Next(4))
sequenceThatFails.on(.Next("🔴"))
sequenceThatFails.on(.Next("🐱"))
sequenceThatFails.on(.Next("🐵"))
sequenceThatFails.on(.Next("🐷"))
sequenceThatFails.on(.Error(NSError(domain: "Test", code: 0, userInfo: nil)))
}
@ -75,23 +75,23 @@ 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 funnyLookingSequence = Observable<Int>.create { observer in
let funnyLookingSequence = Observable<String>.create { observer in
let error = NSError(domain: "Test", code: 0, userInfo: nil)
observer.on(.Next(0))
observer.on(.Next(1))
observer.on(.Next(2))
observer.on(.Next("🏉"))
observer.on(.Next("🎱"))
observer.on(.Next("🏐"))
if count < 2 {
observer.on(.Error(error))
count += 1
}
observer.on(.Next(3))
observer.on(.Next(4))
observer.on(.Next(5))
observer.on(.Next("🔴"))
observer.on(.Next("🐱"))
observer.on(.Next("🐵"))
observer.on(.Completed)
return NopDisposable.instance
}
_ = funnyLookingSequence
.retry()
.subscribe {

View File

@ -28,9 +28,9 @@ Emit only those items from an Observable that pass a predicate test
*/
example("filter") {
let subscription = Observable.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
let subscription = Observable.of("🐶","🐱","🐭","🐹","🐰","🐸","🐱","🐼","🐨","🐱","🐸","🐱","🐷","🐽","🐸","🐱","🐵")
.filter {
$0 % 2 == 0
$0 == "🐱"
}
.subscribe {
print($0)
@ -48,7 +48,7 @@ Suppress duplicate items emitted by an Observable
[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)
let subscription = Observable.of("🐶","🐱","🐱","🐱","🐱","🐱","🐱","🐱","🐱","🐱","🐱","🐷","🐵")
.distinctUntilChanged()
.subscribe {
print($0)
@ -56,6 +56,27 @@ example("distinctUntilChanged") {
}
/*:
### `elementAt`
Emit only item n of all elemets emitted by an Observable
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/elementat.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/elementat.html )
*/
example("elementAt") {
let subscription = Observable.of("🔴","🔵","⚪️","㊗️")
.elementAt(2)
.subscribe {
print($0)
}
}
/*:
### `take`
@ -66,7 +87,7 @@ 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 subscription = Observable.of(1, 2, 3, 4, 5, 6)
let subscription = Observable.of("🐶","🐱","🐭","🐹")
.take(3)
.subscribe {
print($0)
@ -75,4 +96,84 @@ example("take") {
/*:
### `single` (a.k.a first)
Emit only the first item (or the first item that meets some condition) emitted by an Observable
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/first.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/first.html )
*/
example("single") {
let subscription = Observable.of("🐶","🐱","🐭","🐹")
.single()
.subscribe {
print($0)
}
}
example("single with predicate") {
let subscription = Observable.of("🐶","🐱","🐭","🐹")
.single {
$0 == "🔵"
}
.subscribe {
print($0)
}
}
/*:
### `takeLast`
Emit only the final n items emitted by an Observable
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/takelast.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/takelast.html )
*/
example("takeLast") {
let subscription = Observable.of("🐶","🐱","🐭","🐹")
.takeLast(2)
.subscribe {
print($0)
}
}
/*:
### `skip`
Suppress the first n items emitted by an Observable
![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/skip.png)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/skip.html )
*/
example("skip") {
let subscription = Observable.of("🐶","🐱","🐭","🐹")
.skip(2)
.subscribe {
print($0)
}
}
example("skipWhileWithIndex") {
let subscription = Observable.of("🐱","🐱","🐱","🐷","🐷","🐷")
.skipWhileWithIndex { str, idx -> Bool in
return idx < 2
}
.subscribe {
print($0)
}
}
//: [Index](Index) - [Next >>](@next)

View File

@ -12,15 +12,16 @@
## 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)
1. [How to subscribe to Observable sequences](Subscribing_to_Observables)
1. [Operators that create Observable sequences](Creating_Observables)
1. [Subjects - act both as an Observer and as an Observable sequence](Subjects)
1. [Operators that transform Observable sequences](Transforming_Observables)
1. [Operators that filter Observable sequences](Filtering_Observables)
1. [Operators that combine Observable sequences](Combining_Observables)
1. [Operators that handle error notifications from Observable sequences](Error_Handling_Operators)
1. [Operators that conditionally transform Observable sequences depending on Booleans or emissions from other Observable sequences](Conditional_and_Boolean_Operators)
1. [Operators that perform operations on all the items emitted by Observable sequences](Mathematical_and_Aggregate_Operators)
1. [Operators that control how Observable sequences are connected to observers](Connectable_Observable_Operators)
*/

View File

@ -20,179 +20,49 @@ import Foundation
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.
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.
### Concepts
The key to understanding RxSwift is by understanding the notion of Observables as **sequences** of elements.
The next step is to learn how to **create** them, **manipulate** them, and finally **subscribe** to them. Subscribing is needed in order to start the computation and the reception of the elements.
If an Observable emits an `Event.Next` (an element of the sequence), it can still send events. However, if the Observable emits an `Event.Error` (the Observable sequece terminates with an error) or `Event.Completed` (the Observable sequence has completed without error), the Observable won't ever emit more events.
Sequence grammar explains this more concisely.
`Next* (Error | Completed)?`
## Subscription to Observables sequences
Creating an Observable is one thing, but if nothing subscribes to the observable then nothing will happen. In other words, an arbitrary number of `Next` events (sequence elements) will only be emitted after at least one subscription has been made. No more events will be produced after an `Error` or `Completed` has been emitted.
The following closure of the Observable will never be called:
*/
## 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.
*/
/*:
### 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)
}
}
/*:
### never
`never` creates a sequence that never sends any element or completes.
*/
example("never") {
let neverSequence = Observable<Int>.never()
let subscription = neverSequence
.subscribe { _ in
print("This block is never called.")
}
_/* : Observable<String>*/ = Observable<String>.create { observerOfString -> Disposable in
print("This never will be printed")
observerOfString.on(.Next("😬"))
observerOfString.on(.Completed)
return NopDisposable.instance
}
/*:
### just
`just` represents a sequence that contains just one element. It sends two messages to subscribers. The first message is the value of a single element and the second message is `.Completed`.
*/
However, the closure in the following is called:
*/
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)
}
}
/*:
### toObservable
`toObservable` creates a sequence out of an array.
*/
example("toObservable") {
let sequenceFromArray = [1, 2, 3, 4, 5].toObservable()
let subscription = sequenceFromArray
.subscribe { event in
print(event)
}
}
/*:
### create
`create` creates sequence using a Swift closure. This examples creates a custom version of the `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
}
_/* : Observable<String>*/ = Observable<String>.create { observerOfString -> Disposable in
print("Observable creation")
observerOfString.on(.Next("😉"))
observerOfString.on(.Completed)
return NopDisposable.instance
}
let subscription = myJust(5)
.subscribe { event in
print(event)
}
}
.subscribe { print($0) }
/*:
### generate
`generate` creates a sequence that generates values for as long as the provided condition evaluates to `true`.
*/
example("generate") {
let generated = Observable.generate(
initialState: 0,
condition: { $0 < 3 },
iterate: { $0 + 1 }
)
let subscription = generated
.subscribe { event in
print(event)
}
}
/*:
### error
create an Observable that emits no items and immediately terminates with an error
*/
example("error") {
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 are many more useful methods in the RxCocoa library, so check them out:
* `rx_observe` exists on every NSObject and wraps KVO.
* `rx_tap` exists on buttons and wraps @IBActions
* `rx_notification` wraps NotificationCenter events
* ... and many others
*/
The subscription will be present in the whole Rx.playground.
*/
//: [Index](Index) - [Next >>](@next)

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

@ -40,11 +40,11 @@ example("PublishSubject") {
let subject = PublishSubject<String>()
writeSequenceToConsole("1", sequence: subject).addDisposableTo(disposeBag)
subject.on(.Next("a"))
subject.on(.Next("b"))
subject.on(.Next("🐶"))
subject.on(.Next("🐱"))
writeSequenceToConsole("2", sequence: subject).addDisposableTo(disposeBag)
subject.on(.Next("c"))
subject.on(.Next("d"))
subject.on(.Next("🅰️"))
subject.on(.Next("🅱️"))
}
@ -65,11 +65,11 @@ example("ReplaySubject") {
let subject = ReplaySubject<String>.create(bufferSize: 1)
writeSequenceToConsole("1", sequence: subject).addDisposableTo(disposeBag)
subject.on(.Next("a"))
subject.on(.Next("b"))
subject.on(.Next("🐶"))
subject.on(.Next("🐱"))
writeSequenceToConsole("2", sequence: subject).addDisposableTo(disposeBag)
subject.on(.Next("c"))
subject.on(.Next("d"))
subject.on(.Next("🅰️"))
subject.on(.Next("🅱️"))
}
@ -86,13 +86,13 @@ When an observer subscribes to a `BehaviorSubject`, it begins by emitting the it
example("BehaviorSubject") {
let disposeBag = DisposeBag()
let subject = BehaviorSubject(value: "z")
let subject = BehaviorSubject(value: "🔴")
writeSequenceToConsole("1", sequence: subject).addDisposableTo(disposeBag)
subject.on(.Next("a"))
subject.on(.Next("b"))
subject.on(.Next("🐶"))
subject.on(.Next("🐱"))
writeSequenceToConsole("2", sequence: subject).addDisposableTo(disposeBag)
subject.on(.Next("c"))
subject.on(.Next("d"))
subject.on(.Next("🅰️"))
subject.on(.Next("🅱️"))
subject.on(.Completed)
}
@ -105,13 +105,13 @@ example("BehaviorSubject") {
*/
example("Variable") {
let disposeBag = DisposeBag()
let variable = Variable("z")
let variable = Variable("🔴")
writeSequenceToConsole("1", sequence: variable.asObservable()).addDisposableTo(disposeBag)
variable.value = "a"
variable.value = "b"
variable.value = "🐶"
variable.value = "🐱"
writeSequenceToConsole("2", sequence: variable.asObservable()).addDisposableTo(disposeBag)
variable.value = "c"
variable.value = "d"
variable.value = "🅰️"
variable.value = "🅱️"
}
//: [Index](Index) - [Next >>](@next)

View File

@ -0,0 +1,112 @@
/*:
> # 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](Index) - [<< Previous](@previous)
import RxSwift
import Foundation
/*:
# Subscribing to Observable sequences
There are several ways to subscribe to Observable sequences. Here are a few examples:
*/
example("subscribe to receive raw events") {
let sequenceOfJustOneRedCircle/* : Observable<String> */ = Observable.just("🔴")
let subscription = sequenceOfJustOneRedCircle
.subscribe { event in
print("Sequence emit \(event)")
}
}
example("subscribe with optional callbacks per event type") {
let sequenceOfJustOneRedCircle/* : Observable<String> */ = Observable.just("🔴")
let subscription = sequenceOfJustOneRedCircle
.subscribe(onNext: {
print("Emission element of sequence is \($0)")
},
onError: {
print("Oops an error occurred \($0)")
},
onCompleted: {
print("Sequence completed")
},
onDisposed: {
print("Sequence disposed")
})
}
example("subscribe only to emitted elements") {
let sequenceOfJustOneRedCircle/* : Observable<String> */ = Observable.just("🔴")
let subscription = sequenceOfJustOneRedCircle
.subscribeNext {
print("Emitted element of sequence is \($0)")
}
}
example("subscribe only to the completed event") {
let sequenceOfJustOneRedCircle/* : Observable<String> */ = Observable.just("🔴")
let subscription = sequenceOfJustOneRedCircle
.subscribeCompleted {
print("Sequence completed")
}
}
example("subscribe only to the error event, (no error ocurred so nothing is printed)") {
let sequenceOfJustOneRedCircle/* : Observable<String> */ = Observable.just("🔴")
let subscription = sequenceOfJustOneRedCircle
.subscribeError { error in
print("Oops an error occurred \(error)")
}
}
/*:
## Side effects
It is not advisable to leave the Rx monad. (That is not pure reactive programming). But, if desired there is the `doOn` operator.
### `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<String>()
_ = sequenceOfInts
.doOn {
print("Intercepted event \($0)")
}
.subscribe {
print("Sequence emit event \($0)")
}
sequenceOfInts.on(.Next("🍐"))
sequenceOfInts.on(.Completed)
}
//: [Index](Index) - [Next >>](@next)

View File

@ -34,7 +34,9 @@ example("map") {
.map { number in
number * 2
}
.subscribe { print($0) }
.subscribe {
print($0)
}
}
@ -49,9 +51,9 @@ Transform the items emitted by an Observable into Observables, then flatten the
*/
example("flatMap") {
let sequenceInt = Observable.of(1, 2, 3)
let sequenceString = Observable.of("A", "B", "C", "D", "E", "F", "--")
let sequenceString = Observable.of("🐶","🐱","🐭","🐹")
_ = sequenceInt
.flatMap { (x:Int) -> Observable<String> in
print("from sequenceInt \(x)")

View File

@ -3,12 +3,13 @@
<pages>
<page name='Index'/>
<page name='Introduction'/>
<page name='Subscribing_to_Observables'/>
<page name='Creating_Observables'/>
<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='Mathematical_and_Aggregate_Operators'/>
<page name='Connectable_Observable_Operators'/>