Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

47
SWIFT & REACTIVEX Asynchronous Event-Based Funsies with RxSwift

Transcript of Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

Page 1: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

SWIFT & REACTIVEXAsynchronous Event-Based Funsies with RxSwift

Page 2: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

WHO I AM➤ Aaron Douglas

➤ Milwaukee, WI USA

➤ Mobile Maker for Automattic (WordPress.com)

➤ Remote full time 3+ years

➤ @astralbodies

Page 3: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

REACTIVE?FUNCTIONAL?

MEH?

Page 4: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

FUNCTIONAL & REACTIVE PROGRAMMING

➤ Reactive Programming

➤ Asynchronous Data Flow

➤ Functional Programming

➤ Map, Reduce, Filter

➤ Avoiding State

➤ Immutable Data

➤ Declarative Paradigm - logic of computation rather than describing flow

➤ Implementations - ReactiveCocoa/RAC, RxSwift

Page 5: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

WHAT IS RXSWIFT?

Page 6: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

WHAT IS RXSWIFT?

➤ Based on ReactiveX

➤ Many different ports: Java, JavaScript, .NET, Scala, Clojure, Swift, Kotlin, PHP, …

➤ Extends the Observer Pattern

➤ Related to Iterable Pattern

➤ Swift itself provides some protocols with equivalence

➤ SequenceType

➤ GeneratorType

Page 7: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

OBSERVER PATTERN

Page 8: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

NSNOTIFICATIONCENTER

NSNotificationCenter .defaultCenter() .addObserver(self, selector:"downloadImage:", name: "BLDownloadImageNotification", object: nil)

NSNotificationCenter .defaultCenter() .postNotificationName("BLDownloadImageNotification", object: self, userInfo: ["imageView": coverImage, "coverUrl": albumCover])

Page 9: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

OBSERVER PATTERN

9

Page 10: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

ITERATOR PATTERN

Page 11: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

ITERATOR PATTERN

Page 12: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

GENERATORS, SEQUENCES, OH MY!

Page 13: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

GENERATORS

public protocol GeneratorType { associatedtype Element public mutating func next() -> Self.Element? }

Page 14: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

GENERATORSclass CountdownGenerator: GeneratorType { typealias Element = Int var element: Element init<T>(array: [T]) { self.element = array.count } func next() -> Element? { guard element > 0 else { return nil } element -= 1 return element } }

let xs = ["A", "B", "C"] let generator = CountdownGenerator(array: xs) while let i = generator.next() { print("Element \(i) of the array is \(xs[i])") }

Element 2 of the array is C Element 1 of the array is B Element 0 of the array is A

Page 15: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

SEQUENCES

public protocol SequenceType { associatedtype Generator : GeneratorType public func generate() -> Self.Generator }

Page 16: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

SEQUENCESclass ReverseSequence<T>: SequenceType { var array: [T] init(array: [T]) { self.array = array } func generate() -> CountdownGenerator { return CountdownGenerator(array: array) } }

let reverseSequence = ReverseSequence(array: xs) let reverseGenerator = reverseSequence.generate()

while let i = reverseGenerator.next() { print("Index \(i) is \(xs[i])") }

for i in ReverseSequence(array: xs) { print("Index \(i) is \(xs[i])") }

Index 2 is C Index 1 is B Index 0 is A

Index 2 is C Index 1 is B Index 0 is A

Page 17: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

OBSERVABLES

Page 18: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

OBSERVERTYPE

public protocol ObserverType { associatedtype E

func on(event: Event<E>) }

public enum Event<Element> { case Next(Element) case Error(ErrorType) case Completed }

Page 19: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

OBSERVABLETYPE

public protocol ObservableType : ObservableConvertibleType { associatedtype E func subscribe<O: ObserverType where O.E == E>(observer: O) -> Disposable }

public protocol ObservableConvertibleType { associatedtype E

func asObservable() -> Observable<E> }

Page 20: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

VISUALIZATIONS OF SEQUENCES

--1--2--3--4--5--6--| // terminates normally

--a--b--a--a--a---d---X // terminates with error

---tap-tap-------tap---> // infinite; never ends

Page 21: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

MAKING AN OBSERVABLE

let disposeBag = DisposeBag() Observable.just("X") .subscribe { event in print(event) } .addDisposableTo(disposeBag)

Page 22: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

MAKING AN OBSERVABLE

let disposeBag = DisposeBag() Observable.of("W", "X", "Y", "X") .subscribeNext { element in print(element) } .addDisposableTo(disposeBag)

Page 23: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

MAKING AN OBSERVABLE

let disposeBag = DisposeBag() ["W", "X", "Y", "Z"].toObservable() .subscribeNext { print($0) } .addDisposableTo(disposeBag)

Page 24: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

SUBSCRIBING

someObservable.subscribe( onNext: { print("Element: ", $0) }, onError: { print("Error: ", $0) }, onCompleted: { print("Completed") }, onDisposed: { print("Disposed") } )

someObservable .subscribeNext { print("Element: ", $0) }

Page 25: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

OPERATORS

Page 26: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift
Page 27: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

MAP

Page 28: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

MAP

let disposeBag = DisposeBag() Observable.of(1, 2, 3) .map { $0 * 10 } .subscribeNext { print($0) } .addDisposableTo(disposeBag)

---

10 20 30

Page 29: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

FILTER

Page 30: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

FILTER

let disposeBag = DisposeBag()

Observable.of(2, 30, 22, 5, 60, 1) .filter { $0 > 10 } .subscribeNext { print($0) } .addDisposableTo(disposeBag)

---

30 22 60

Page 31: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

SCAN

Page 32: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

SCANlet disposeBag = DisposeBag() Observable.of(1, 2, 3, 4, 5) .scan(0) { aggregateValue, newValue in aggregateValue + newValue } .subscribeNext { print($0) } .addDisposableTo(disposeBag)

---

1 3 6 10 15

Page 33: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

MERGE

Page 34: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

MERGElet disposeBag = DisposeBag() let subject1 = PublishSubject<String>() let subject2 = PublishSubject<String>() Observable.of(subject1, subject2) .merge() .subscribeNext { print($0) } .addDisposableTo(disposeBag) subject1.onNext("20") subject1.onNext("40") subject1.onNext("60")

subject2.onNext("1") subject1.onNext("80") subject1.onNext("100")

subject2.onNext("1")

20 40 60 1 80 100 1

Page 35: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

RXMARBLES.COM

Page 36: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

DISPOSING

Page 37: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

.dispose()

Page 38: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

.addDisposableTo(disposeBag)

Page 39: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

COCOA + RXSWIFT

Page 40: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

BINDINGS

totCountStepper .rx_value .subscribeNext { value in self.totalNumberOfTots.value = Int(value) } .addDisposableTo(disposeBag)

Page 41: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

BINDINGS➤ NSTextStorage

➤ UIActivityIndicatorView

➤ UIAlertAction

➤ UIApplication

➤ UIBarButtonItem

➤ UIButton

➤ UICollectionView

➤ UIControl

➤ UIDatePicker

➤ UIGestureRecognizer

➤ UIImagePickerController

➤ UIImageView

➤ UILabel

➤ UINavigationItem

➤ UIPageControl

➤ UIPickerView

➤ UIProgressView

➤ UIRefreshControl

➤ UIScrollView

➤ UISearchBar

➤ UISearchController

➤ UISegmentedControl

➤ UISlider

➤ UIStepper

➤ UISwitch

➤ UITabBar

➤ UITabBarItem

➤ UITableView

➤ UITextField

➤ UITextView

➤ UIView

➤ UIViewController

Page 42: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

AN EXAMPLE

Page 43: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

TATER TOT TIMER

Page 44: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

RXSWIFT IN THE WILD

Page 45: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

WHERE TO LEARN MORE

Page 46: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

WHERE TO LEARN MORE

➤ ReactiveX RxSwift main repo

➤ https://github.com/ReactiveX/RxSwift/

➤ FRP iOS Learning Resources

➤ https://gist.github.com/JaviLorbada/4a7bd6129275ebefd5a6

➤ Functional Reactive Programming with RxSwift

➤ https://realm.io/news/slug-max-alexander-functional-reactive-rxswift/

➤ RxSwift Slack

➤ http://rxswift-slack.herokuapp.com/

Page 47: Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift

AARON DOUGLAS@astralbodies

http://astralbodi.es