FRP in Swift 3 - files.meetup.com

You might already be doing some reactive programming var title: String ... RxSwift , ReactiveCocoa ... //realm.io/news/altconf-ash-furrow-functional-r...

1 downloads 577 Views 3MB Size
FRP in Swift 3 101

© Andy Jacobs, ixor.be 2016

1

Andy Jacobs 7 years iOS development 2 years FRP experience 1.5 year FRP enthusiast

© Andy Jacobs, ixor.be 2016

2

Topics • What? • Why? • Basic concepts • Real world example • Tip

© Andy Jacobs, ixor.be 2016

3

What? streams of values over time

© Andy Jacobs, ixor.be 2016

4

What? streams of values over time + operations and bindings

© Andy Jacobs, ixor.be 2016

5

Streams

© Andy Jacobs, ixor.be 2016

6

Operations Most operators operate on a given stream and will return a stream. This allows you to apply these operators one after the other, in a chain. Each operator in the chain modifies the stream that results from the operation of the previous operator.

© Andy Jacobs, ixor.be 2016

7

Common Operators // Creating create, just, from, .. // Transforming map, flatMap, scan, .. // Filtering filter, skip, take, .. // Combining combineLatest, merge, zip, .. // Utility subscribe, delay, observeOn, .. // Conditional takeUntil, skipWhile, .. // Mathematical & Aggregate concat, reduce, .. // Connectable publish, replay, connect, .. © Andy Jacobs, ixor.be 2016

8

Bindings bind the stream of values to an endpoint. • Subjects • Variables • UI

© Andy Jacobs, ixor.be 2016

9

Why? You might already be doing some reactive programming var title: String { didSet { // react to changes in variables view.titleLabel.text = title } }

© Andy Jacobs, ixor.be 2016

10

Heavy lifting Libraries as RxSwift, ReactiveCocoa, ReactKit, Bond, .. bring so much more to the table.

© Andy Jacobs, ixor.be 2016

11

RxSwift, ReactiveX In short, using Rx will make your code: Composable ⇠ Because Rx is composition's nickname Reusable ⇠ Because it's composable Declarative ⇠ Because definitions are immutable and only data changes Understandable and concise ⇠ Raising the level of abstraction and removing transient states Stable ⇠ Because Rx code is thoroughly unit tested Less stateful ⇠ Because you are modeling applications as unidirectional data flows Without leaks ⇠ Because resource management is easy

© Andy Jacobs, ixor.be 2016

12

Basic concepts • Observable • Event • Disposing • Subjects • Hot vs Cold • Schedulers © Andy Jacobs, ixor.be 2016

13

Observable Every Observable sequence is just a sequence. The key advantage for an Observable vs Swift's Sequence is that it can also receive elements asynchronously.

© Andy Jacobs, ixor.be 2016

14

Event Each value in the stream is defined as an event. • Next • Error • Completed

© Andy Jacobs, ixor.be 2016

15

Interface enum Event { case next(Element) // next element of a sequence case error(Swift.Error) // sequence failed with error case completed // sequence terminated successfully } class Observable { func subscribe(_ observer: Observer) -> Disposable }

Sequences can have 0 or more elements. Once an error or completed event is received, the sequence cannot produce any other element. © Andy Jacobs, ixor.be 2016

16

Disposing A Disposable is used to disconnect the observable wrapper from its source, causing subscribed observer to stop receiving values from the underlying observable sequence. error, completed, dispose(), takeUntil all internal resources that compute sequence elements will be freed © Andy Jacobs, ixor.be 2016

17

Subjects A Subject is a sort of bridge or proxy that is available in some implementations of Rx that acts as both an observer and Observable. Because it is an observer, it can subscribe to one or more Observables, and because it is an Observable, it can pass through the items it observes by reemitting them, and it can also emit new items.

© Andy Jacobs, ixor.be 2016

18

Subjects • PublishSubject Broadcasts new events to all observers as of their time of the subscription. • ReplaySubject Broadcasts new events to all subscribers, and the specified bufferSize number of previous events to new subscribers. • BehaviorSubject Broadcasts new events to all subscribers, and the most recent (or initial) value to new subscribers. • Variable Wraps a BehaviorSubject, so it will emit the most recent (or initial) value to new subscribers. And Variable also maintains current value state. Variable will never emit an Error event. However, it will automatically emit a Completed event and terminate on deinit. © Andy Jacobs, ixor.be 2016

19

Hot ! vs Cold ❄

© Andy Jacobs, ixor.be 2016

20

! vs ❄ (demo)

© Andy Jacobs, ixor.be 2016

21

Schedulers Schedulers abstract away the mechanism for performing work. Different mechanisms for performing work include the current thread, dispatch queues, operation queues, new threads, thread pools, and run loops. • CurrentThreadScheduler (default, serial) • MainScheduler (serial) • SerialDispatchQueueScheduler (serial) • ConcurrentDispatchQueueScheduler (concurrent) • OperationQueueScheduler (concurrent) © Andy Jacobs, ixor.be 2016

22

Real world example live coding

© Andy Jacobs, ixor.be 2016

23

Tips

When you are using Rx, first try to compose built-in operators. rxmarbles.com, rxmarbles.appstor.io

© Andy Jacobs, ixor.be 2016

24

Tips

When you are using Rx, first try to compose built-in operators. rxmarbles.com, rxmarbles.appstor.io

© Andy Jacobs, ixor.be 2016

25

Tips

If using some (combination of) operators often, create your convenience operators. extension ObservableType where E: MaybeCool { @warn_unused_result(message="http://git.io/rxs.uo") public func coolElements() -> Observable { return filter { e -> Bool in return e.isCool } } } © Andy Jacobs, ixor.be 2016

26

Tips

Avoid nesting subscribe calls at all cost textField.rx_text.subscribe(onNext: { text in performURLRequest(text).subscribe(onNext: { result in ... }) .addDisposableTo(disposeBag) }) .addDisposableTo(disposeBag)

© Andy Jacobs, ixor.be 2016

27

Tips

Preferred way of chaining disposables by using operators. textField.rx_text .flatMapLatest { text in // Assuming this doesn't fail and returns result on main scheduler, // otherwise `catchError` and `observeOn(MainScheduler.instance)` can be used to // correct this. return performURLRequest(text) } ... .addDisposableTo(disposeBag) // only one top most disposable

© Andy Jacobs, ixor.be 2016

28

Credits..

• RxSwift documentation • https://www.youtube.com/watch?v=7AqXBuJOJkY • https://realm.io/news/nacho-soto-functional-reactiveprogramming/ • https://realm.io/news/altconf-ash-furrow-functional-reactiveswift/

© Andy Jacobs, ixor.be 2016

29

rxdevcon.com Saturday, October 7, 2017

© Andy Jacobs, ixor.be 2016

30

Questions?

© Andy Jacobs, ixor.be 2016

31

Thank you —

© Andy Jacobs, ixor.be 2016

@avalanched

32