reactive thinking in ios development - pedro piñera buendía - codemotion amsterdam 2016

84
REACTIVE THINKING IN IOS DEVELOPMENT @PEPIBUMUR / @SAKY

Upload: codemotion

Post on 09-Jan-2017

376 views

Category:

Technology


2 download

TRANSCRIPT

Page 1: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

REACTIVE THINKING IN IOS DEVELOPMENT

@PEPIBUMUR / @SAKY

Page 2: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

WHO?

@pepibumuriOS Developer at SoundCloud

GitHub: pepibumurTwitter: pepibumur

@sakyiOS Developer at Letgo

GitHub: isaacroldanTwitter: saky

GitDo.io our spare time project

Page 3: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

INDEX

> Programming Paradigms> Reactive Libraries

> Reactive Motivation> Reactive Thinking> Reactive Caveats

> Conclusion

Page 4: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

PARADIGMS !WAYS OF SEEING THE WORLD WHEN IT COMES TO PROGRAMMING

Page 5: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

WIKIPEDIA

Data-Driven, Declarative, Dynamic, End-User, Event-Driven, Expression-Oriented, Feature-Oriented, Function-level,

Generic, Imperative, Inductive, Language Oriented, Metaprogramming, Non-Structured, Nondeterministic,

Parallel computing, Point-free Style, Structured, Value-Level, Probabilistic

Page 6: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

IMPERATIVE PROGRAMMINGDECLARATIVE PROGRAMMING

Page 7: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

IMPERATIVE PROGRAMMINGDECLARATIVE PROGRAMMING

Page 8: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

HOWSEQUENCE OF STEPS

THAT HAPPEN IN ORDER

Page 9: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

NATURAL WAY TO PROGRAM

Page 10: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

EXECUTION STATE(AKA SIDE EFFECT)

Page 11: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

IMPERATIVE PROGRAMMING

func userDidSearch(term: String) { let apiReults = api.search(term: term).execute() self.items = self.adaptResults(apiResults) self.tableView.reloadData()}

Page 12: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

IMPERATIVE PROGRAMMINGDECLARATIVE PROGRAMMING

Page 13: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

WHATIT DOESN'T DESCRIBE THE

CONTROL FLOW

Page 14: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

HTML

Page 15: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

HTMLSQL

Page 16: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

HTMLSQL

REACTIVE PROGRAMMING

Page 17: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

DECLARATIVE PROGRAMMING

let predicate = NSPredicate(format: "name == %@", "Pedro")let regex = NSRegularExpression(pattern: ".+", options: 0)

Page 18: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

REACTIVE PROGRAMMINGDATA-FLOW PROGRAMMING

(DESCRIBES THE STATE PROPAGATION)

# THE INTRODUCTION TO REACTIVE PROGRAMMING THAT YOU'VE BEEN MISSING

Page 19: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

FUNCTIONAL REACTIVE PROGRAMMING

(AKA FRP)

Page 21: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

WHAT LIBRARY SHOULD I USE? !

Page 22: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

WHAT LIBRARY SHOULD I USE? !DO I NEED A LIBRARY FOR THIS? !

Page 23: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

SWIFT

var userName: String { didSet { // React to changes in variables

}}

Page 24: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

SWIFT

var userName: String { didSet { // React to changes in variables view.updateTitle(userName) }}

Page 25: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

MOTIVATION !WHY SHOULD I STICK TO REACTIVE PROGRAMMING?

Page 26: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

> Bindings> Composability

> Threading

Page 27: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

> Bindings> Composability

> Threading

Page 28: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

BINDING

Page 29: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

UI BINDING

Page 30: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

UI BINDING

Page 31: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

UI BINDING

Page 32: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

> Bindings> Composability

> Threading

Page 33: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016
Page 34: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016
Page 35: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

> Bindings> Composability

> Threading

Page 36: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

> Bindings> Composability

> Threading (observer and execution)

Page 37: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

THREADING

Page 38: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

REACTIVE THINKING !

Page 39: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

THINKING IN TERMS OF

OBSERVABLESOR SIGNALS/PRODUCERS IN REACTIVECOCOA

Page 40: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

ACTIONS CAN BE

OBSERVEDHOW? !

Page 41: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

.NEXT(T).ERROR(ERRORTYPE)

.COMPLETE

Page 42: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

OPERATIONS

RxSwiftObservable<String>.create { (observer) -> Disposable in observer.onNext("next value") observer.onCompleted() return NopDisposable.instance // For disposing the action}

ReactiveCocoaSignalProducer<String>.create { (observer, disposable) in observer.sendNext("next value") observer.sendComplete()}

Page 43: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

EXISTING PATTERNSRXSWIFT ▶︎ RXCOCOA (EXTENSIONS)

REACTIVECOCOA ▶︎ DO IT YOURSELF

Page 44: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

UIKITlet button = UIButton()button.rx_controlEvent(.TouchUpInside) .subscribeNext { _ in print("The button was tapped") }

Page 45: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

NOTIFICATIONSNSNotificationCenter.defaultCenter() .rx_notification("my_notification", object: nil) .subscribeNext { notification // We got a notification }

Page 46: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

DELEGATESself.tableView.rx_delegate // DelegateProxy .observe(#selector(UITableViewDelegate.tableView(_:didSelectRowAtIndexPath:))) .subscribeNext { (parameters) in // User did select cell at index path }

Page 47: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

PLAYING !WITH OBSERVABLES

Page 48: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

OBSERVABLE

let tracksFetcher = api.fetchTracks // Background .asObservable()

Page 49: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

ERROR HANDLING

let tracksFetcher = api.fetchTracks // Background .asObservable() .retry(3) .catchErrorJustReturn([])

Page 50: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

MAPPING

let tracksFetcher = api.fetchTracks // Background .asObservable() .retry(3) .catchErrorJustReturn([]) .map(TrackEntity.mapper().map)

Page 51: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

FILTERING

let tracksFetcher = api.fetchTracks // Background .asObservable() .retry(3) .catchErrorJustReturn([]) .map(TrackEntity.mapper().map) .filter { $0.name.contains(query) }

Page 52: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

FLATMAPPING

let tracksFetcher = api.fetchTracks // Background .asObservable() .retry(3) .catchErrorJustReturn([]) .map(TrackEntity.mapper().map) .filter { $0.name.contains(query) } .flatMap { self.rx_trackImage(track: $0) }

Page 53: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

OBSERVATION THREAD

let tracksFetcher = api.fetchTracks // Background .asObservable() .retry(3) .catchErrorJustReturn([]) .map(TrackEntity.mapper().map) .filter { $0.name.contains(query) } .flatMap { self.rx_trackImage(track: $0) } .observeOn(MainScheduler.instance) // Main thread

Page 54: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

LE IMPERATIVE WAY !"func fetchTracks(retry retry: Int = 0, retryLimit: Int, query: query, mapper: (AnyObject) -> Track, completion: ([UIImage], Error?) -> ()) { api.fetchTracksWithCompletion { (json, error) in if let _ = error where retry < retryLimit { fetchTracksWithRetry(retry: retry+1, retryLimit: retryLimit, query: query, mapper: mapper, completion: completion) } else if let error = error { completion([], error) } else if let json = json { guard let jsonArray = json as? [AnyObject] else { completion([], Error.InvalidResponse) return } let mappedTracks = jsonArray.map(mapper) let filteredTracks = mappedTracks.filter { $0.name.contains(query) } self.fetchImages(track: filteredTracks, completion: ([])) let trackImages = self.fetchImages(tracks: filteredTracks, completion: { (images, error) in dispatch_async(dispatch_get_main_queue(),{ if let error = error { completion([], error) return } completion(images, error) }) }) } }}

Page 55: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

THROTTLINGCLASSIC REACTIVE EXAMPLE

func tracksFetcher(query: String) -> Observable<[TrackEntity]>

searchTextField .rx_text.throttle(0.5, scheduler: MainScheduler.instance) .flatmap(tracksFetcher) .subscribeNext { tracks in // Yai! Tracks searched }

Page 56: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

OTHER OPERATORS

Combining / Skipping Values / Deferring / Concatenation / Take some values / Zipping

Page 57: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

OBSERVING !EVENTS

Page 58: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

SUBSCRIBING

observable subscribe { event switch (event) { case .Next(let value): print(value) case .Completed: print("completed") case .Error(let error): print("Error: \(error)") } }

Page 59: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

BIND CHANGES OVER THE TIME TO AN OBSERVABLE

OBSERVABLE ▶ BINDING ▶ OBSERVER

Page 60: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

BINDING

To a Variablelet myVariable: Variable<String> = Variable("")observable .bindTo(myVariable)print(myVariable.value)

To UIobservable .bindTo(label.rx_text)

Page 61: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016
Page 62: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

! CAVEATSBECAUSE YES...

IT COULDN'T BE PERFECT

Page 63: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

DEBUGGINGDEBUG OPERATOR IN RXSWIFT

Page 64: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

let tracksFetcher = api.fetchTracks // Background .asObservable() .retry(3) .catchErrorJustReturn([]) .map(TrackEntity.mapper().map) .filter { $0.name.contains(query) } .flatMap { self.rx_trackImage(track: $0) } .observeOn(MainScheduler.instance) // Main thread

Page 65: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

let tracksFetcher = api.fetchTracks // Background .asObservable .debug("after_fetch") // <-- Debugging probes .retry(3) .catchErrorJustReturn([]) .map(TrackEntity.mapper().map) .debug("mapped_results") // <-- Debugging probes .filter { $0.name.contains(query) } .flatMap { self.rx_trackImage(track: $0) } .observeOn(MainScheduler.instance) // Main thread

Page 66: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

//let tracksFetcher = api.fetchTracks // Background// .asObservable .debug("after_fetch") // <-- Debugging probes// .retry(3)// .catchErrorJustReturn([])// .map(TrackEntity.mapper().map) .debug("mapped_results") // <-- Debugging probes// .filter { $0.name.contains(query) }// .flatMap { self.rx_trackImage(track: $0) }// .observeOn(MainScheduler.instance) // Main thread

Page 67: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

> [after_fetch] Next Event... // Downloaded tracks> [mapped_results] Error ... // Detected error after mapping> [...]

Page 68: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

RETAIN CYCLES

class IssuePresenter { var disposable: Disposable

func fetch() { self.disposable = issueTitle .observable() .bindTo { self.titleLabel.rx_text } }}

Page 69: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

UNSUBSCRIPTIONYOU NEED TO TAKE CARE OF THE

LIFECYCLE OF YOUR OBSERVABLES

Page 70: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

UNSUBSCRIPTION

title.asObservable().bindTo(field.rx_text)

// RxSwift will show a warning

Page 71: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

UNSUBSCRIPTION

let titleDisposable = title.asObservable().bindTo(field.rx_text)titleDisposable.dispose()

Page 72: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

UNSUBSCRIPTION

let disposeBag = DisposeBag()

title.asObservable() .bindTo(field.rx_text) .addDisposableTo(disposeBag)

// The binding is active until the disposeBag is deallocated

Page 73: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

CONCLUSIONS

Page 74: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

PREVENTS STATEFUL CODE

Page 75: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

DATA FLOW MANIPULATION BECOMES EASIER

Page 76: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

BUT... !

Page 77: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

YOU COUPLE YOUR PROJECT TO A LIBRARY

!

Page 78: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

REACTIVE CODE SPREADS LIKE A VIRUS !

OVERREACTIVE ⚠

Page 79: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

DEFINE REACTIVE DESIGN GUIDELINES AND STICK TO

THEM

Page 80: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

HAVE REACTIVE FUN !

Page 81: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

REFERENCES

> rxmarbles.com> RxSwift Community> RxSwift Repository

> ReactiveCocoa

Page 82: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

WE ARE [email protected] - [email protected]

❄ BERLIN - BARCELONA !

Page 83: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016
Page 84: Reactive Thinking in iOS Development - Pedro Piñera Buendía - Codemotion Amsterdam 2016

THANKSQUESTIONS?SLIDES HTTP://BIT.LY/1RFWLCI

@SAKY - @PEPIBUMUR