Slide 1

Slide 1 text

RxSwift A gentle introduction “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 2

Slide 2 text

Guille González @gonzalezreal “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 3

Slide 3 text

http://reactivex.io “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 4

Slide 4 text

Observer on steroids “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 5

Slide 5 text

Taps, keyboard events, timers, GPS events, web service responses ↓ UI update, data written to disk, API request, etc. “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 6

Slide 6 text

Asynchronous Events in Cocoa → Target-Action → NSNotificationCenter → Key-Value Observing → Delegates → Callback Closures “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 7

Slide 7 text

Observable “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 8

Slide 8 text

--1--2--3--4--5-|---> --a--b--b--a--✕-----> ---tap-tap----tap---> ---JSON-|-----------> -|------------------> -✕------------------> “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 9

Slide 9 text

enum Event { case Next(Element) case Error(ErrorType) case Completed } “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 10

Slide 10 text

--Next("a")--Next("b")--Error(diskError)-> -----Next---Next-------Next--------------> ---Next(json)-Completed------------------> “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 11

Slide 11 text

Creating Observables → Observable.empty() → Observable.just("!") → Observable.of("!", """, "⚽") → Observable.error(Error.CouldNotDecodeJSON) “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 12

Slide 12 text

Creating Observables let o = Observable.create { observer in observer.on(.Next("! world!")) observer.on(.Completed) return NopDisposable.instance } “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 13

Slide 13 text

If a tree falls in a forest and no one is around to hear it, does it make a sound? — George Berkeley “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 14

Slide 14 text

┌─────────────────────────────────────┬─────────────────────────────────────┐ │ Hot Observables │ Cold observables │ ├─────────────────────────────────────┼─────────────────────────────────────┤ │Use resources even when there are no │Don't use resources until there is a │ │subscribers. │subscriber. │ ├─────────────────────────────────────┼─────────────────────────────────────┤ │Resources usually shared between all │Resources usually allocated per │ │the subscribers. │subscriber. │ ├─────────────────────────────────────┼─────────────────────────────────────┤ │Usually stateful. │Usually stateless. │ ├─────────────────────────────────────┼─────────────────────────────────────┤ │UI controls, taps, sensors, etc. │HTTP request, async operations, etc. │ └─────────────────────────────────────┴─────────────────────────────────────┘ “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 15

Slide 15 text

Observers protocol ObservableType { func subscribe(on: (event: Event) -> Void) -> Disposable } “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 16

Slide 16 text

Observers Observable.create { observer in observer.onNext("! world!") observer.onCompleted() return NopDisposable.instance }.subscribe { event in print(event) } // outputs: // Next(! world!) // Completed “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 17

Slide 17 text

Observers Observable.create { observer in observer.onNext("! world!") observer.onCompleted() return NopDisposable.instance }.subscribeNext { text in print(text) } // outputs: // ! world! “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 18

Slide 18 text

Disposables let appleWeb = Observable.create { observer in let task = session.dataTaskWithURL(appleURL) { data, response, error in if let data = data { observer.onNext(data) observer.onCompleted() } else { observer.onError(error ?? Error.UnknownError) } } task.resume() return AnonymousDisposable { task.cancel() } } “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 19

Slide 19 text

Dispose Bags self.disposeBag = DisposeBag() ... appleWeb.subscribeNext { data in print(data) }.addDisposableTo(disposeBag) “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 20

Slide 20 text

Operators → map → flatMap → filter → throttle → merge → combineLatest → and many more... “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 21

Slide 21 text

map & flatMap struct Country { let name: String let borders: [String] } protocol CountriesAPI { func countryWithName(name: String) -> Observable func countriesWithCodes(codes: [String]) -> Observable<[Country]> } “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 22

Slide 22 text

map & flatMap myAPI.countryWithName("spain") .flatMap { country in myAPI.countriesWithCodes(country.borders) } .map { countries in countries.map { $0.name } } .subscribeNext { countryNames in print(countryNames) } “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 23

Slide 23 text

Observable chaining is similar to Optional chaining: let cell = UITableViewCell(style: .Default, reuseIdentifier: nil) let maybeSize = cell.imageView?.image?.size let maybeSize2 = cell.imageView.flatMap { $0.image }.flatMap { $0.size } “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 24

Slide 24 text

observeOn myAPI.countryWithName("spain") .flatMap { country in myAPI.countriesWithCodes(country.borders) } .map { countries in countries.map { $0.name } } .observeOn(MainScheduler.instance) .subscribeNext { countryNames in // Main thread, all good } “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 25

Slide 25 text

“RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 26

Slide 26 text

throttle let results = searchBar.rx_text .throttle(0.3, scheduler: MainScheduler.instance) .flatMapLatest { query in if query.isEmpty { return Observable.just([]) } return searchShows(query) } .observeOn(MainScheduler.instance) .shareReplay(1) “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 27

Slide 27 text

combineLatest Observable.combineLatest(emailField.rx_text, passwordField.rx_text) { email, password in return email.characters.count > 0 && password.characters.count > 0 } .bindTo(sendButton.rx_enabled) .addDisposableTo(disposeBag) “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 28

Slide 28 text

Follow-up Resources → reactivex.io → rxmarbles.com → github.com/ReactiveX/RxSwift → tinyurl.com/consuming-web-services “RxSwift, A gentle introduction” - Guille González @gonzalezreal

Slide 29

Slide 29 text

Questions? Comments? “RxSwift, A gentle introduction” - Guille González @gonzalezreal