Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RxSwift - A primer

RxSwift - A primer

The slides for a talk I gave at CocoaHeads Belgium on November 22, 2017 about RxSwift.
The demo project can be found at https://github.com/frederik-jacques/cocoaheads-rxswift-primer

Frederik Jacques

November 22, 2017
Tweet

Other Decks in Programming

Transcript

  1. RxSwift
    and how we use it in production apps
    frederik jacques - @thenerd_be 1

    View Slide

  2. Hello
    frederik jacques - @thenerd_be 2

    View Slide

  3. Hello
    • Frederik Jacques
    • Lecturer Devine (Howest University College)
    • Living in The Netherlands (what was I thinking)
    • Freelance iOS consultant
    • Currently working at Nederlandse Spoorwegen
    frederik jacques - @thenerd_be 3

    View Slide

  4. frederik jacques - @thenerd_be 4

    View Slide

  5. RxSwift
    frederik jacques - @thenerd_be 5

    View Slide

  6. RxSwift
    • What is it?
    • Observables / Observers
    • Subjects
    • Operators
    • Debugging
    • Unit Testing
    • Live demo
    frederik jacques - @thenerd_be 6

    View Slide

  7. RxSwift
    • Reactive library
    • Part of http://reactivex.io
    • Same api over different language ports
    frederik jacques - @thenerd_be 7

    View Slide

  8. frederik jacques - @thenerd_be 8

    View Slide

  9. Nutshell definition
    frederik jacques - @thenerd_be 9

    View Slide

  10. Handling asynchronous
    code by observing a
    stream of values.
    — Yours truly
    frederik jacques - @thenerd_be 10

    View Slide

  11. !
    frederik jacques - @thenerd_be 11

    View Slide

  12. Remember
    notifications?
    frederik jacques - @thenerd_be 12

    View Slide

  13. Here we are observing a certain event.
    NotificationCenter.default
    .addObserver( forName: Notification.Name.UserDidLogin, object: self, queue: nil )
    { (notification) in
    print("User did login")
    }
    frederik jacques - @thenerd_be 13

    View Slide

  14. !
    Observer
    Observable
    frederik jacques - @thenerd_be 14

    View Slide

  15. Observable
    The thing that sends out stuff
    — Yours truly
    frederik jacques - @thenerd_be 15

    View Slide

  16. Observer
    The thing that's interested in the data from the observable
    — Yours truly
    frederik jacques - @thenerd_be 16

    View Slide

  17. Observable
    • The key element of RxSwift
    • Concept?
    • Produce a sequence of immutable events
    • 3 types of event: next, completed & error
    frederik jacques - @thenerd_be 17

    View Slide

  18. frederik jacques - @thenerd_be 18

    View Slide

  19. Types of streams
    1. Infinite streams
    2. Finite streams
    • Completes
    • Errors out
    frederik jacques - @thenerd_be 19

    View Slide

  20. frederik jacques - @thenerd_be 20

    View Slide

  21. frederik jacques - @thenerd_be 21

    View Slide

  22. frederik jacques - @thenerd_be 22

    View Slide

  23. Subjects
    frederik jacques - @thenerd_be 23

    View Slide

  24. Subjects
    1. Variable
    2. PublishSubject
    3. BehaviorSubject
    4. ReplaySubject
    frederik jacques - @thenerd_be 24

    View Slide

  25. Variable
    • Easiest one to get started with
    let names = Variable(["Frederik"])
    frederik jacques - @thenerd_be 25

    View Slide

  26. Variable
    • Get the current value
    let nameValue = names.value
    frederik jacques - @thenerd_be 26

    View Slide

  27. Variable
    • Getting updates
    names.asObservable()
    .subscribe(onNext: { (theNames) in
    print(theNames)
    })
    frederik jacques - @thenerd_be 27

    View Slide

  28. Variable
    • Putting elements on the stream
    names.value.append("Tom")
    names.value.append("Spencer")
    frederik jacques - @thenerd_be 28

    View Slide

  29. Variable
    • Putting it all together
    let names = Variable(["Frederik"])
    names.asObservable()
    .subscribe(onNext: { (theNames) in
    print(theNames)
    })
    names.value.append("Tom")
    names.value.append("Spencer")
    frederik jacques - @thenerd_be 29

    View Slide

  30. PublishSubject
    • Subscribers get all the upcoming events (NOT the current
    one)
    let nameSubject = PublishSubject()
    • Add data on the stream with onNext method
    nameSubject.onNext("Frederik")
    frederik jacques - @thenerd_be 30

    View Slide

  31. PublishSubject
    let nameSubject = PublishSubject()
    nameSubject.onNext("Frederik")
    nameSubject.subscribe(onNext: { (name) in
    print("Name = \(name)")
    })
    nameSubject.onNext("Steven")
    frederik jacques - @thenerd_be 31

    View Slide

  32. PublishSubject
    let nameSubject = PublishSubject()
    nameSubject.subscribe(onNext: { (name) in
    print("Name = \(name)")
    })
    nameSubject.onNext("Frederik")
    nameSubject.onNext("Steven")
    frederik jacques - @thenerd_be 32

    View Slide

  33. BehaviorSubject
    • Subscribers get all upcoming events + the current value
    let nameSubject = BehaviorSubject(value: "Frederik")
    • Add data on the stream with onNext method
    nameSubject.onNext("Steven")
    frederik jacques - @thenerd_be 33

    View Slide

  34. BehaviorSubject
    let nameSubject = BehaviorSubject(value: "Frederik")
    nameSubject.onNext("Steven")
    nameSubject.subscribe(onNext: { (name) in
    print("Name = \(name)")
    })
    nameSubject.onNext("Spencer")
    frederik jacques - @thenerd_be 34

    View Slide

  35. ReplaySubject
    • Subscribers get all upcoming events + the amount specified
    in the buffer from earlier events
    let nameSubject = ReplaySubject.create(bufferSize: 2)
    • Add data on the stream with onNext method
    nameSubject.onNext("Frederik")
    frederik jacques - @thenerd_be 35

    View Slide

  36. ReplaySubjects
    let nameSubject = ReplaySubject.create(bufferSize: 1)
    nameSubject.onNext("Frederik")
    nameSubject.onNext("Steven")
    nameSubject.subscribe(onNext: { (name) in
    print("Name = \(name)")
    })
    nameSubject.onNext("Spencer")
    frederik jacques - @thenerd_be 36

    View Slide

  37. Disposebags
    frederik jacques - @thenerd_be 37

    View Slide

  38. Disposebags
    A container in which your subscriptions are stored, so they
    don't get deallocated within the local scope of a function or
    get properly disposed when you class gets deallocated
    frederik jacques - @thenerd_be 38

    View Slide

  39. Disposebags
    // Somewhere at the top
    private let disposeBag = DisposeBag()
    ///////
    // Somewhere else
    let nameSubject = ReplaySubject.create(bufferSize: 1)
    nameSubject.onNext("Frederik")
    nameSubject.onNext("Steven")
    nameSubject.subscribe(onNext: { (name) in
    print("Name = \(name)")
    }).disposed(by: disposeBag)
    nameSubject.onNext("Spencer")
    frederik jacques - @thenerd_be 39

    View Slide

  40. Sharing is caring
    frederik jacques - @thenerd_be 40

    View Slide

  41. Sharing is caring
    • Every subscription, triggers the observable
    • Share an observable to avoid this (e.g. network requests)
    • share()
    • share(replay: 1, scope: .forever)
    • share(replay: 1, scope: .whileConnected)
    frederik jacques - @thenerd_be 41

    View Slide

  42. Operators
    frederik jacques - @thenerd_be 42

    View Slide

  43. Operators
    • Marble diagrams
    frederik jacques - @thenerd_be 43

    View Slide

  44. frederik jacques - @thenerd_be 44

    View Slide

  45. Filter
    • Filter out elements
    .filter({ (device) -> Bool in
    return device == "iPad" || device == "iPhone"
    })
    frederik jacques - @thenerd_be 45

    View Slide

  46. Map
    • Map from one thing to something else
    Observable.just( 18 )
    .map { (age) -> String in
    guard age > 16 else {
    return "Not allowed to drink"
    }
    return "Allowed to drink"
    }
    frederik jacques - @thenerd_be 46

    View Slide

  47. Take
    • Take x-number of elements from the start of the stream and
    complete
    frederik jacques - @thenerd_be 47

    View Slide

  48. Skip
    • Skip x-number of elements before receiving elements on
    the stream
    frederik jacques - @thenerd_be 48

    View Slide

  49. Distinct
    • Only allow unique elements in the stream
    • Use distinctUntilChanged if doubles are allowed, but not
    one after each other
    frederik jacques - @thenerd_be 49

    View Slide

  50. Combining
    observables
    frederik jacques - @thenerd_be 50

    View Slide

  51. CombineLatest
    • Combine 2 (or more) observables, but only if both have
    emitted at least one element
    frederik jacques - @thenerd_be 51

    View Slide

  52. WithLatestFrom
    • Request the value of the last element of another stream
    frederik jacques - @thenerd_be 52

    View Slide

  53. Debugging
    frederik jacques - @thenerd_be 53

    View Slide

  54. Debugging
    Debugging is hard, the most encountered issues
    1. it doesn't trigger
    2. it triggers too much
    frederik jacques - @thenerd_be 54

    View Slide

  55. Debugging
    • use debug() operator in the chain
    frederik jacques - @thenerd_be 55

    View Slide

  56. Schedulers
    frederik jacques - @thenerd_be 56

    View Slide

  57. Schedulers
    • Have nothing to do with threading
    • A context where a process takes place (can be a thread,
    dispatch_queue, NSOperation, ...).
    frederik jacques - @thenerd_be 57

    View Slide

  58. Schedulers
    ObserveOn
    • Where does the code of the observer run
    • 99% of the cases, you'll be using this one
    frederik jacques - @thenerd_be 58

    View Slide

  59. Schedulers
    SubscribeOn
    • Where does the code of the observable run
    frederik jacques - @thenerd_be 59

    View Slide

  60. Unit Testing
    Quite easy to do
    • RxTest: Most code
    • RxBlocking: Block thread until you get result
    frederik jacques - @thenerd_be 60

    View Slide

  61. RxSwift add-ons
    • RxCocoa
    • RxSwiftExt
    • RxDataSources
    • Check RxSwift Community for more!
    frederik jacques - @thenerd_be 61

    View Slide

  62. Great resources
    • Slack Channel
    • RxSwift Book (Ray Wenderlich)
    • Marin Todorov's blog
    • Droids on roids blog
    • Rx.playground (in RxSwift GitHub repo)
    frederik jacques - @thenerd_be 62

    View Slide

  63. Demo
    frederik jacques - @thenerd_be 63

    View Slide

  64. Thank you
    frederik jacques - @thenerd_be 64

    View Slide

  65. Q&A?
    frederik jacques - @thenerd_be 65

    View Slide