reactive programming with rxswift

Post on 16-Apr-2017

930 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

RXSWIFTREACTIVE PROGRAMMING WITH

WHO AM I?

▸ iOS developer since 2010

▸ Swift since day 1

▸ Transitioning to Swift

▸ CocoaConf

▸ Wash U

▸ RayWenderlich.com

▸ lynda.com

WHO ARE YOU?

▸ iOS developer

▸ How long?

▸ Swift developer

▸ How long?

▸ Reactive programming

▸ ReactiveCocoa

▸ Reactive Extensions

WHAT IS REACTIVE PROGRAMMING?

REACTVE PROGRAMMING IS ESSENTIALLY WORKING WITH ASYNCHRONOUS DATA STREAMS

@fpillet

ABOUT REACTIVE EXTENSIONS

▸ Event-driven

▸ Asynchronous

▸ Functional

▸ Common patterns

▸ Observer

▸ Iterator

▸ Cross-platform

CANONICAL EXAMPLE

IMPERATIVE

a = 3 b = 4 c = a + b // 7 a = 6 c // 7

CANONICAL EXAMPLE

REACTIVE

a = 3 b = 4 c = a + b a = 6 c // 10

// 7

TRADITIONAL VS. REACTIVEA SIMPLE EXAMPLE IN IOS

MODEL

VIEW MODEL

VIEW CONTROLLER

REACTIVE VIEW MODEL

REACTIVE VIEW CONTROLLER

THE RESULTS

40% LESS

Environment

Interactive

Reactive

Program

REACTIVE EXTENSIONS

Nov. ‘09

Rx.NET

RxJS

Mar. ‘10

RxJava

Mar. ‘12

RxCpp

Nov. ‘12

RxRuby

Dec. ‘12

RxSca

la, RxC

lojure, RxG

roovy, RxJR

uby

Jan. ‘1

3

RxPY, R

xPHP

Mar. ‘13

RxKotlin

Oct. ‘1

3

RxSwift

Feb. ‘1

5

REACTIVE MANIFESTO

RX STANDARDIZES THE PATTERNS & OPERATORS USED TO DEVELOP ASYNCHRONOUS APPS IN MULTIPLE ENVIRONMENTS.

RXSWIFT OPERATORS

▸ Creating

asObservable

create

deferred

empty

error

toObservable

interval

never

just

of

range

repeatElement

timer

▸ Transforming

buffer

flatMap

flatMapFirst

flatMapLatest

map

scan

window

▸ Filtering

debounce / throttle

distinctUntilChanged

elementAt

filter

sample

skip

take

takeLast

single

▸ Conditional & Boolean

amb

skipWhile

skipUntil

takeUntil

takeWhile

▸ Mathematical & Aggregate

concat

reduce

toArray

▸ Connectable

multicast

publish

refCount

replay

shareReplay

▸ Combining

merge

startWith

switchLatest

combineLatest

zip

▸ Error Handling

catch

retry

retryWhen

▸ Observing

delaySubscription

do / doOnNext

observeOn

subscribe

subscribeOn

timeout

using

debug

LIFECYCLE OF AN OBSERVABLE (AKA SEQUENCE)

▸ onNext

▸ onError

▸ onComplete

▸ dispose() / DisposeBag

DO YOU HAZ TEH CODEZ ?!?

SETUP

▸ Install ThisCouldBeUsButYouPlaying

▸ bit.ly/podsPlaygrounds

▸ gem install cocoapods-playgrounds

▸ Create RxSwiftPlayground

▸ pod playgrounds RxSwift

SETUP

//: Please build the scheme 'RxSwiftPlayground' first import XCPlayground XCPlaygroundPage.currentPage.needsIndefiniteExecution = true

import RxSwift

SETUP

//: Please build the scheme 'RxSwiftPlayground' first import XCPlayground XCPlaygroundPage.currentPage.needsIndefiniteExecution = true

import RxSwift

func exampleOf(description: String, action: Void -> Void) { print("\n--- Example of:", description, "---") action() }

--- Example of: just --- Next(32) Completed

exampleOf("just") {

Observable.just(32) .subscribe {

print($0)

}

}

CREATING & SUBSCRIBING

--- Example of: just --- Next(32) Completed

exampleOf("just") {

Observable.just(32) .subscribe { value in

print(value)

}

}

CREATING & SUBSCRIBING

--- Example of: just --- 32

exampleOf("just") {

_ = Observable.just(32).subscribeNext { print($0) }

}

CREATING & SUBSCRIBING

--- Example of: of --- 1 2 3 4 5

exampleOf("of") {

Observable.of(1, 2, 3, 4, 5) .subscribeNext { print($0) } .dispose()

}

CREATING & SUBSCRIBING

--- Example of: toObservable --- 1 2 3

exampleOf("toObservable") { let disposeBag = DisposeBag() [1, 2, 3].toObservable() .subscribeNext { print($0) } .addDisposableTo(disposeBag) }

CREATING & SUBSCRIBING

--- Example of: BehaviorSubject --- Next(Hello) Next(World!)

exampleOf("BehaviorSubject") { let disposeBag = DisposeBag() let string = BehaviorSubject(value: "Hello") string.subscribe { print($0) } .addDisposableTo(disposeBag) string.onNext("World!") }

CREATING & SUBSCRIBING

CREATING & SUBSCRIBING

--- Example of: Variable --- Next(1) Next(12) Next(1234567) Completed

exampleOf("Variable") { let disposeBag = DisposeBag() let number = Variable(1) number.asObservable() .subscribe { print($0) } .addDisposableTo(disposeBag) number.value = 12 number.value = 1_234_567 }

exampleOf("map") { Observable.of(1, 2, 3) .map { $0 * $0 } .subscribeNext { print($0) } .dispose() }

TRANSFORMING

--- Example of: map --- 1 4 9

TRANSFORMING

--- Example of: Variable and map --- one twelve one million two hundred thirty-four thousand five hundred sixty-seven

exampleOf("Variable and map") { let disposeBag = DisposeBag() let numberFormatter = NSNumberFormatter() numberFormatter.numberStyle = .SpellOutStyle let number = Variable(1) number.asObservable() .map { numberFormatter.stringFromNumber($0)! } .subscribeNext { print($0) } .addDisposableTo(disposeBag) number.value = 12 number.value = 1_234_567 }

TRANSFORMING

--- Example of: flatMap --- Scott Lori Eric

exampleOf("flatMap") { let disposeBag = DisposeBag() struct Person { var name: Variable<String> } let scott = Person(name: Variable("Scott")) let lori = Person(name: Variable("Lori")) let person = Variable(scott) person.asObservable() .flatMap { $0.name.asObservable() } .subscribeNext { print($0) } .addDisposableTo(disposeBag) person.value = lori scott.name.value = "Eric" }

TRANSFORMING

--- Example of: flatMapLatest --- Scott Lori

exampleOf("flatMap") { let disposeBag = DisposeBag() struct Person { var name: Variable<String> } let scott = Person(name: Variable("Scott")) let lori = Person(name: Variable("Lori")) let person = Variable(scott) person.asObservable() .flatMapLatest { $0.name.asObservable() } .subscribeNext { print($0) } .addDisposableTo(disposeBag) person.value = lori scott.name.value = "Eric" }

exampleOf("distinctUntilChanged") { let disposeBag = DisposeBag() let searchString = Variable("iOS") searchString.asObservable() .map { $0.lowercaseString } .distinctUntilChanged() .subscribeNext { print($0) } .addDisposableTo(disposeBag) searchString.value = "IOS" searchString.value = "Rx" searchString.value = "ios" }

FILTERING

--- Example of: distinctUntilChanged --- ios rx ios

exampleOf("combineLatest") { let disposeBag = DisposeBag() let number = PublishSubject<Int>() let string = PublishSubject<String>() Observable.combineLatest(number, string) { "\($0) \($1)" } .subscribeNext { print($0) } .addDisposableTo(disposeBag) number.onNext(1) print("Nothing yet") string.on(.Next("A")) number.onNext(2) string.onNext("B") string.onNext("C") }

COMBINING

--- Example of: combineLatest --- Nothing yet 1 A 2 A 2 B 2 C

exampleOf("takeWhile") { [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1].toObservable() .takeWhile { $0 < 5 } .subscribeNext { print($0) } .dispose() }

CONDITIONAL

--- Example of: takeWhile --- 1 2 3 4

MATHEMATICAL

--- Example of: reduce --- 1024

exampleOf("reduce") { [1, 2, 4, 8, 16].toObservable() .reduce(1, accumulator: *) .subscribeNext { print($0) } .dispose() }

ERROR HANDLING

--- Example of: error --- A

exampleOf("error") { enum Error: ErrorType { case A } Observable<Int>.error(Error.A) .subscribeError { // Handle error print($0) } .dispose() }

RXMARBLES

RXSWIFTPLAYER

OBJECTIONS

1. Dependency

2. Complexity

3. Performance

4. Debugging

5. Help

BENEFITS

1. Write less, do more

2. Avoid mutable state errors

3. Learn once, apply everywhere

4. Mix in or go all in

5. “It reads almost like a paragraph”

6. Easy to test and heavily tested

QUESTIONS?

WANT MORE RX?

▸ github.com/ReactiveX/RxSwift

▸ reactivex.io

▸ rxmarbles.com

▸ rxswift.slack.com

▸ rx-marin.com

▸ http://as.ync.io

▸ github.com/scotteg/RxSwiftPlayer

▸ github.com/Artsy/eidolon

THANK YOU!

Scott Gardner @scotteg as.ync.io bit.ly/scottOnLyndaDotCom

top related