Operators
There are numerous operators implemented in RxSwift.
Marble diagrams for all operators can be found on ReactiveX.io
Almost all operators are demonstrated in Playgrounds.
To use playgrounds please open Rx.xcworkspace
, build RxSwift-macOS
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.
Custom operators
There are two ways how you can create custom operators.
Easy way
All of the internal code uses highly optimized versions of operators, so they aren't the best tutorial material. That's why it's highly encouraged to use standard operators.
Fortunately there is an easier way to create operators. Creating new operators is actually all about creating observables, and previous chapter already describes how to do that.
Lets see how an unoptimized map operator can be implemented.
extension ObservableType {
func myMap<R>(transform: E -> R) -> Observable<R> {
return Observable.create { observer in
let subscription = self.subscribe { e in
switch e {
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)
}
}
return subscription
}
}
}
So now you can use your own map:
let subscription = myInterval(0.1)
.myMap { e in
return "This is simply \(e)"
}
.subscribe(onNext: { n in
print(n)
})
and this will print
Subscribed
This is simply 0
This is simply 1
This is simply 2
This is simply 3
This is simply 4
This is simply 5
This is simply 6
This is simply 7
This is simply 8
...
Life happens
So what if it's just too hard to solve some cases with custom operators? You can exit the Rx monad, perform actions in imperative world, and then tunnel results to Rx again using Subject
s.
This isn't something that should be practiced often, and is a bad code smell, but you can do it.
let magicBeings: Observable<MagicBeing> = summonFromMiddleEarth()
magicBeings
.subscribe(onNext: { being in // exit the Rx monad
self.doSomeStateMagic(being)
})
.addDisposableTo(disposeBag)
//
// Mess
//
let kitten = globalParty( // calculate something in messy world
being,
UIApplication.delegate.dataSomething.attendees
)
kittens.on(.next(kitten)) // send result back to rx
//
// Another mess
//
let kittens = Variable(firstKitten) // again back in Rx monad
kittens.asObservable()
.map { kitten in
return kitten.purr()
}
// ....
Every time you do this, somebody will probably write this code somewhere
kittens
.subscribe(onNext: { kitten in
// so something with kitten
})
.addDisposableTo(disposeBag)
so please try not to do this.