Share
Embed
Transcript
95 slides
-
dataProvider.refreshData() .subscribe( onNext: { [weak self] in self!?.update(with: $0) },
onError: { [weak self] in if let error = $0 as? ReasonableError { self!?.showUserMessage(with: error.reason) } } ) .disposed(by: disposeBag) -
dataProvider.refreshData() .subscribe( onNext: { [weak self] in self!?.update(with: $0) },
onError: { [weak self] in if let error = $0 as? ReasonableError { self!?.showUserMessage(with: error.reason) } } ) .disposed(by: disposeBag) -
dataProvider.refreshData() .subscribe( onNext: { [weak self] in self!?.update(with: $0) },
onError: { [weak self] in if let error = $0 as? ReasonableError { self!?.showUserMessage(with: error.reason) } } ) .disposed(by: disposeBag) -
dataProvider.refreshData() .subscribe( onNext: { [weak self] in self!?.update(with: $0) },
onError: { [weak self] in if let error = $0 as? ReasonableError { self!?.showUserMessage(with: error.reason) } } ) .disposed(by: disposeBag) -
dataProvider.refreshData() .subscribe( onNext: { [weak self] in self!?.update(with: $0) },
onError: { [weak self] in if let error = $0 as? ReasonableError { self!?.showUserMessage(with: error.reason) } } ) .disposed(by: disposeBag) -
dataProvider.refreshData() .subscribe( onNext: { [weak self] in self!?.update(with: $0) },
onError: { [weak self] in if let error = $0 as? ReasonableError { self!?.showUserMessage(with: error.reason) } } ) .disposed(by: disposeBag) -
Observable .just(42) .filter { $0 > 30 } .map {
“\($0)” } Just Filter Map -
Observable .just(42) .filter { $0 > 30 } .map {
“\($0)” } .distinctUntilChanged { $0 !== $1 } Just Filter Map Distinct UntilChanged -
let observable: Observable<String> = Observable .just(42) .filter { $0 >
30 } .map { “\($0)” } .distinctUntilChanged { $0 !== $1 } Just Filter Map observable observable -
environment Observable .just(42) .filter { $0 > 30 } .map
{ “\($0)” } .distinctUntilChanged { $0 !== $1 } Just Filter Map Distinct UntilChanged filter closure compare closure map closure -
Observable .just(42) .filter { $0 > 30 } .map {
“\($0)” } .distinctUntilChanged { $0 !== $1 } .subscribe { print($0) } Just Filter Map Distinct UntilChanged filter closure compare closure map closure Just Sink Filter Sink Map Sink DUC Sink -
Observable .just(42) .filter { $0 > 30 } .map {
“\($0)” } .distinctUntilChanged { $0 !== $1 } .subscribe { print($0) } Just Filter Map Distinct UntilChanged filter closure compare closure map closure Just Sink Filter Sink Map Sink DUC Sink -
Observable .just(42) .filter { $0 > 30 } .map {
“\($0)” } .distinctUntilChanged { $0 !== $1 } .subscribe { print($0) } Just Filter Map Distinct UntilChanged filter closure compare closure map closure Just Sink Filter Sink Map Sink DUC Sink Observer Observer -
filter closure compare closure map closure Just Sink Filter Sink
Map Sink DUC Sink Observer Just Sink Disposer Filter Sink Disposer Map Sink Disposer DUC Sink Disposer Observable .just(42) .filter { $0 > 30 } .map { “\($0)” } .distinctUntilChanged { $0 !== $1 } .subscribe { print($0) } -
reference cycles filter closure compare closure map closure Just Sink
Filter Sink Map Sink DUC Sink Observer Just Sink Disposer Filter Sink Disposer Map Sink Disposer DUC Sink Disposer -
filter closure compare closure map closure Just Sink Filter Sink
Map Sink DUC Sink Observer Just Sink Disposer Filter Sink Disposer Map Sink Disposer disposable let disposable: Disposable = Observable .just(42) .filter { $0 > 30 } .map { “\($0)” } .distinctUntilChanged { $0 !== $1 } .subscribe { print($0) } -
disposable .dispose() filter closure compare closure map closure Just Sink
Filter Sink Map Sink DUC Sink Observer Just Sink Disposer Filter Sink Disposer Map Sink Disposer disposable -
.dispose() — called externally on subscription disposable — called
internally when event stream ends -
filter closure compare closure map closure Just Sink Filter Sink
Map Sink DUC Sink Observer Just Sink Disposer Filter Sink Disposer Map Sink Disposer disposable observe closure let disposable = Observable .just(42) .filter { $0 > 30 } .map { “\($0)” } .distinctUntilChanged { $0 !== $1 } .subscribe { print($0) } -
environment let disposable = Observable .just(42) .filter { $0 >
30 } .map { “\($0)” } .distinctUntilChanged { $0 !== $1 } .subscribe { print($0) } filter closure compare closure map closure Just Sink Filter Sink Map Sink DUC Sink Observer Just Sink Disposer Filter Sink Disposer Map Sink Disposer disposable observe closure -
observable .map { [weak self] in self!?.transform($0) } .subscribe {
[weak self] in self!?.react(to: $0) } observable .map { [unowned self] in self.transform($0) } .subscribe { [unowned self] in self.react(to: $0) } .disposed( by: self.disposeBag ) -
!// instance method func foo(_ bar: Int) !-> Int !//
instance scope Observable.just(42) .map(foo) !// instance method func foo(_ bar: Int) !-> Int !// instance scope Observable.just(42) .map { self.foo($0) } -
dataProvider.refreshData() .subscribe( onNext: { [weak self] in self!?.update(with: $0) },
onError: { [weak self] in if let error = $0 as? ReasonableError { self!?.showUserMessage(with: error.reason) } } ) .disposed(by: disposeBag) -
dataProvider.refreshData() .subscribe( onNext: { [unowned self] in self.update(with: $0) },
onError: { [unowned self] in if let error = $0 as? ReasonableError { self.showUserMessage(with: error.reason) } } ) .disposed(by: disposeBag) -
dataProvider.refreshData() .subscribe( onNext: { [unowned self] in self.update(with: $0) },
onError: { [unowned self] in if let error = $0 as? ReasonableError { self.showUserMessage(with: error.reason) } } ) .disposed(by: disposeBag) -
ImmediateSchedulerType func schedule<StateType>( _ state: StateType, action: @escaping (StateType) !->
Disposable ) !-> Disposable -
MainScheduler let mainQueue = DispatchQueue.main !// simplified essence of schedule
method if DispatchQueue.isMain { action(state) } else { mainQueue.async { action(state) } } -
SerialDispatchQueueScheduler !// internal serial dispatch queue of given properties let
queue = DispatchQueue.global(qos: qos.qosClass) !// simplified essence of schedule method queue.async { action(state) } -
OperationQueueScheduler !// operation queue provided by client in the initializer
let operationQueue: OperationQueue !// simplified essence of schedule method operationQueue.addOperation( BlockOperation { action(state)) } ) -
Also in schedulers • QOS • serial / concurrent •
immediate / delayed • driven by client -
Scheduler-agnostic operators map { foo($0) } flatMap { bar($0) }
filter { $0 !== wanted } -
Observable .just(42) .filter { $0 > 33 } .map {
"\($0)" } .subscribe { print($0) } .disposed(by: disposeBag) Subscription thread -
Observable .just(42) .observeOn(greenScheduler) .filter { $0 > 33 } .map
{ "\($0)" } .subscribe { print($0) } .disposed(by: disposeBag) Subscription thread Green scheduler -
Observable .just(42) .observeOn(greenScheduler) .filter { $0 > 33 } .observeOn(redScheduler)
.map { "\($0)" } .observeOn(greenScheduler) .subscribe { print($0) } .disposed(by: disposeBag) Subscription thread Red scheduler Green scheduler Green scheduler -
Observable .just(42) .observeOn(greenScheduler) .filter { $0 > 33 } .observeOn(redScheduler)
.subscribeOn(blueScheduler) .map { "\($0)" } .observeOn(greenScheduler) .subscribe { print($0) } .disposed(by: disposeBag) Blue scheduler Red scheduler Green scheduler Green scheduler -
Observable .just(42) .observeOn(greenScheduler) .filter { $0 > 33 } .subscribeOn(blueScheduler)
.observeOn(redScheduler) .subscribeOn(redScheduler) .map { "\($0)" } .observeOn(greenScheduler) .subscribeOn(greenScheduler) .subscribe { print($0) } .disposed(by: disposeBag) Blue scheduler Red scheduler Green scheduler Green scheduler -
Observable .just( 42, scheduler: blueScheduler ) .observeOn(greenScheduler) .filter { $0
> 33 } .observeOn(redScheduler) .subscribeOn(redScheduler) .map { "\($0)" } .observeOn(greenScheduler) .subscribe { print($0) } .disposed(by: disposeBag) Blue scheduler Red scheduler Green scheduler Green scheduler -
Schedule-using for generation !// Scheduler to send elements on. .fromScheduled([1,
2, 3], greenScheduler) !// Scheduler to run the producer loop on. .repeatElement(1, blueScheduler) !// Scheduler to run the timer on. .interval(1, redScheduler) -
Schedule-using for internal work !// Scheduler to run the throttle
timers on. .throttle(1, blueScheduler) !// Scheduler to run the subscription delay timer on. .delay(1, greenScheduler) !// Scheduler to run buffering timers on. .buffer(timeSpan: 1, count: 3, scheduler: redScheduler) -
Observable<Int> .merge([ Observable<Int>.interval(3, redScheduler), Observable<Int>.interval(5, greenScheduler), ]) .subscribe { [unowned
self] in !// sometimes red, sometimes green self.work(with: $0) } .disposed(by: disposeBag) -
dataProvider.refreshData() .observeOn(MainScheduler.instance) .subscribe( onNext: { [unowned self] in self.update(with: $0)
}, onError: { [unowned self] in if let error = $0 as? ReasonableError { self.showUserMessage(with: error.reason) } } ) .disposed(by: disposeBag) -
dataProvider.refreshData() .observeOn(MainScheduler.instance) .subscribe( onNext: { [unowned self] in self.update(with: $0)
}, onError: { [unowned self] in if let error = $0 as? ReasonableError { self.showUserMessage(with: error.reason) } } ) .disposed(by: disposeBag) -
Finishing !// you may ignore disposable (though I recommend not
to!) _ = observable .subscribe(onNext: { [weak self] in self!?.work(on: $0) }) -
Not finishing let disposable = observable .subscribe(onNext: { [weak self]
in self!?.work(on: $0) }) !// ensure subscription disposing disposable.dispose() disposable.disposed(by: disposeBag) -
One-off let serial = SerialDisposable() !// call each time you
want the fresh data func fetchFreshData() { serial.disposable = observable .subscribe(onNext: { [unowned self] in self.work(on: $0) }) } -
Updating let disposeBag = DisposeBag() !// call only once in
the object lifetime func listenForFreshData() { observable .subscribe(onNext: { [unowned self] in self.work(on: $0) }) .disposed(by: disposeBag) } -
Immediately & synchronously !// if not ready to handle data
at the `subscribe` time dataProvider .data() .skip(1) .subscribe(onNext: { [unowned self] in self.work(on: $0) }) .disposed(by: disposeBag) -
After some time & asynchronously !// provide separate method for
fetching initial data let initialData = dataProvider.getInitialData() dataProvider .dataUpdates() .subscribe(onNext: { [unowned self] in self.work(on: $0) }) .disposed(by: disposeBag) -
Not caching let observable = dataProvider .fetchHugeAmountOfDataFromNetwork() !// costly network
request with fresh data observable.subscribe() !// costly network request with fresh data observable.subscribe() -
Caching let observable = dataProvider .fetchHugeAmountOfDataFromNetwork() .shareReplay(1) !// costly network
request with fresh data observable.subscribe() !// no network refresh but also old data observable.subscribe() -
!/* Returns an Observable that emits at most three times,
starting with the first event emitted immediately and synchronously upon subscription. Times of other two events are not guaranteed. May not complete, but never errors out. Doesn’t cache any data. !*/ public func thirdTimeLucky() !-> Observable<Data> -
final class DataProvider { private let proxySubject = PublishSubject<Data>() var
data: Observable<Data> { return proxySubject.asObservable() } func refreshData() !-> Observable<Void> { return networkService .requestData() .do(onNext: { proxySubject.onNext($0) } .map { _ in } } -
dataProvider.refreshData() .observeOn(MainScheduler.instance) .subscribe( onNext: { [unowned self] in self.update(with: $0)
}, onError: { [unowned self] in if let error = $0 as? ReasonableError { self.showUserMessage(with: error.reason) } } ) .disposed(by: disposeBag)