Slide 1

Slide 1 text

SWIFT & REACTIVEX Asynchronous Event-Based Funsies with RxSwift

Slide 2

Slide 2 text

WHO I AM ➤ Aaron Douglas ➤ Milwaukee, WI USA ➤ Mobile Maker for Automattic (WordPress.com) ➤ Remote full time 3+ years ➤ @astralbodies

Slide 3

Slide 3 text

REACTIVE?
 FUNCTIONAL?
 MEH?

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

WHAT IS RXSWIFT?

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

OBSERVER PATTERN

Slide 8

Slide 8 text

NSNOTIFICATIONCENTER NSNotificationCenter .defaultCenter() .addObserver(self, selector:"downloadImage:", name: "BLDownloadImageNotification", object: nil) NSNotificationCenter .defaultCenter() .postNotificationName("BLDownloadImageNotification", object: self, userInfo: ["imageView": coverImage, "coverUrl": albumCover])

Slide 9

Slide 9 text

OBSERVER PATTERN 9

Slide 10

Slide 10 text

ITERATOR PATTERN

Slide 11

Slide 11 text

ITERATOR PATTERN

Slide 12

Slide 12 text

GENERATORS, SEQUENCES, OH MY!

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

GENERATORS class CountdownGenerator: GeneratorType { typealias Element = Int var element: Element init(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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

SEQUENCES class ReverseSequence: 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

Slide 17

Slide 17 text

OBSERVABLES

Slide 18

Slide 18 text

OBSERVERTYPE public protocol ObserverType { associatedtype E func on(event: Event) } public enum Event { case Next(Element) case Error(ErrorType) case Completed }

Slide 19

Slide 19 text

OBSERVABLETYPE public protocol ObservableType : ObservableConvertibleType { associatedtype E func subscribe(observer: O) -> Disposable } public protocol ObservableConvertibleType { associatedtype E func asObservable() -> Observable }

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

OPERATORS

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

MAP

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

FILTER

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

SCAN

Slide 32

Slide 32 text

SCAN let 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

Slide 33

Slide 33 text

MERGE

Slide 34

Slide 34 text

MERGE let disposeBag = DisposeBag() let subject1 = PublishSubject() let subject2 = PublishSubject() 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

Slide 35

Slide 35 text

RXMARBLES.COM

Slide 36

Slide 36 text

DISPOSING

Slide 37

Slide 37 text

.dispose()

Slide 38

Slide 38 text

.addDisposableTo(disposeBag)

Slide 39

Slide 39 text

COCOA + RXSWIFT

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

AN EXAMPLE

Slide 43

Slide 43 text

TATER TOT TIMER

Slide 44

Slide 44 text

RXSWIFT IN THE WILD

Slide 45

Slide 45 text

WHERE TO LEARN MORE

Slide 46

Slide 46 text

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/

Slide 47

Slide 47 text

AARON DOUGLAS @astralbodies http://astralbodi.es