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

B8e8a9c7e39b72963b8ade16d4406a8b?s=128

Frederik Jacques

November 22, 2017
Tweet

Transcript

  1. 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
  2. 6.

    RxSwift • What is it? • Observables / Observers •

    Subjects • Operators • Debugging • Unit Testing • Live demo frederik jacques - @thenerd_be 6
  3. 7.

    RxSwift • Reactive library • Part of http://reactivex.io • Same

    api over different language ports frederik jacques - @thenerd_be 7
  4. 10.

    Handling asynchronous code by observing a stream of values. —

    Yours truly frederik jacques - @thenerd_be 10
  5. 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
  6. 15.
  7. 16.

    Observer The thing that's interested in the data from the

    observable — Yours truly frederik jacques - @thenerd_be 16
  8. 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
  9. 19.

    Types of streams 1. Infinite streams 2. Finite streams •

    Completes • Errors out frederik jacques - @thenerd_be 19
  10. 25.

    Variable • Easiest one to get started with let names

    = Variable<[String]>(["Frederik"]) frederik jacques - @thenerd_be 25
  11. 29.

    Variable • Putting it all together let names = Variable<[String]>(["Frederik"])

    names.asObservable() .subscribe(onNext: { (theNames) in print(theNames) }) names.value.append("Tom") names.value.append("Spencer") frederik jacques - @thenerd_be 29
  12. 30.

    PublishSubject • Subscribers get all the upcoming events (NOT the

    current one) let nameSubject = PublishSubject<String>() • Add data on the stream with onNext method nameSubject.onNext("Frederik") frederik jacques - @thenerd_be 30
  13. 31.

    PublishSubject let nameSubject = PublishSubject<String>() nameSubject.onNext("Frederik") nameSubject.subscribe(onNext: { (name) in

    print("Name = \(name)") }) nameSubject.onNext("Steven") frederik jacques - @thenerd_be 31
  14. 32.

    PublishSubject let nameSubject = PublishSubject<String>() nameSubject.subscribe(onNext: { (name) in print("Name

    = \(name)") }) nameSubject.onNext("Frederik") nameSubject.onNext("Steven") frederik jacques - @thenerd_be 32
  15. 33.

    BehaviorSubject • Subscribers get all upcoming events + the current

    value let nameSubject = BehaviorSubject<String>(value: "Frederik") • Add data on the stream with onNext method nameSubject.onNext("Steven") frederik jacques - @thenerd_be 33
  16. 34.

    BehaviorSubject let nameSubject = BehaviorSubject<String>(value: "Frederik") nameSubject.onNext("Steven") nameSubject.subscribe(onNext: { (name)

    in print("Name = \(name)") }) nameSubject.onNext("Spencer") frederik jacques - @thenerd_be 34
  17. 35.

    ReplaySubject • Subscribers get all upcoming events + the amount

    specified in the buffer from earlier events let nameSubject = ReplaySubject<String>.create(bufferSize: 2) • Add data on the stream with onNext method nameSubject.onNext("Frederik") frederik jacques - @thenerd_be 35
  18. 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
  19. 39.

    Disposebags // Somewhere at the top private let disposeBag =

    DisposeBag() /////// // Somewhere else let nameSubject = ReplaySubject<String>.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
  20. 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
  21. 45.

    Filter • Filter out elements .filter({ (device) -> Bool in

    return device == "iPad" || device == "iPhone" }) frederik jacques - @thenerd_be 45
  22. 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
  23. 47.

    Take • Take x-number of elements from the start of

    the stream and complete frederik jacques - @thenerd_be 47
  24. 48.

    Skip • Skip x-number of elements before receiving elements on

    the stream frederik jacques - @thenerd_be 48
  25. 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
  26. 51.

    CombineLatest • Combine 2 (or more) observables, but only if

    both have emitted at least one element frederik jacques - @thenerd_be 51
  27. 52.

    WithLatestFrom • Request the value of the last element of

    another stream frederik jacques - @thenerd_be 52
  28. 54.

    Debugging Debugging is hard, the most encountered issues 1. it

    doesn't trigger 2. it triggers too much frederik jacques - @thenerd_be 54
  29. 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
  30. 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
  31. 59.
  32. 60.

    Unit Testing Quite easy to do • RxTest: Most code

    • RxBlocking: Block thread until you get result frederik jacques - @thenerd_be 60
  33. 61.

    RxSwift add-ons • RxCocoa • RxSwiftExt • RxDataSources • Check

    RxSwift Community for more! frederik jacques - @thenerd_be 61
  34. 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