functional reactive programming - rxswift

36
Functional Reactive Programming

Upload: rodrigo-leite

Post on 16-Apr-2017

214 views

Category:

Software


8 download

TRANSCRIPT

Page 1: Functional Reactive Programming - RxSwift

Functional Reactive Programming

Page 2: Functional Reactive Programming - RxSwift

About

Rodrigo Freitas co-founder at [email protected]

Page 3: Functional Reactive Programming - RxSwift

Focus on mobile development

OutsourcingProduct Development

Page 4: Functional Reactive Programming - RxSwift
Page 5: Functional Reactive Programming - RxSwift

Functional & Reactive

Page 6: Functional Reactive Programming - RxSwift

Functional &Avoid state

Immutable dataDeclarative programming

Page 7: Functional Reactive Programming - RxSwift

& Reactive

Data drivenValues over time

Streams

Page 8: Functional Reactive Programming - RxSwift

Reactive Cocoa RxSwift

Page 9: Functional Reactive Programming - RxSwift

RxSwift

Based on ReactiveX

Page 10: Functional Reactive Programming - RxSwift

RxSwift

Based on ReactiveX

Observable pattern

Iterator pattern}Functional programming

} Reactive

Page 11: Functional Reactive Programming - RxSwift

Rx.Net

Rx.JS

Rx.Jav

a

Rx.Cpp

Rx.Rub

y

Rx.Sca

la, RxC

losure

Rx.Py, R

xPHP

Rx.Kotl

in

Rx.Swift

Reactive Extensions

nov. 2009mar. 2010

mar. 2012nov. 2012

dec. 2012jan. 2013

mar. 2013out. 2013

feb. 2015

Page 12: Functional Reactive Programming - RxSwift

ObservableEmits events over time

ObserverSubscribe to listen events emitted by the observable

Page 13: Functional Reactive Programming - RxSwift

ObservableLife cycle observable sequence

marble diagrams

// Terminate normally

// Terminate with error

// Endless sequence1 2 3

tap tap tap tap

a b

Page 14: Functional Reactive Programming - RxSwift

ObservableEmits events over time

protocol Observable { associatedtype E func on(_ event: Event<E>) }

enum Event<Element: Any> { case Next(Any) case Error(Error) case Completed }

Page 15: Functional Reactive Programming - RxSwift

ObservableEmits events over time

Array<T>

Observable<T>

Page 16: Functional Reactive Programming - RxSwift

ObservableCreate Operator

let observable = Observable.just("Hello World")

Page 17: Functional Reactive Programming - RxSwift

ObservableListen Operator

let observable = Observable.just("Hello World")

// next(Hello World) // completed

observable.subscribe(onNext: { (value) in print(value) // Pump out an element }, onError: { (error) in // Catch error }, onCompleted: { // Catch completed }, onDisposed: { // Dispose the subscription })

Page 18: Functional Reactive Programming - RxSwift

ObservableCreate Operator

let disposeBag = DisposeBag() Observable.from(["🐶", "🐱", "🐭", "🐹"]) .subscribe(onNext: { print($0) }) .addDisposableTo(disposeBag)

Page 19: Functional Reactive Programming - RxSwift

ObservableCreate Operator

let disposeBag = DisposeBag() Observable.from(["🐶", "🐱", "🐭", "🐹"]) .subscribe(onNext: { print($0) }) .addDisposableTo(disposeBag)

🐶 🐱 🐭 🐹

🐶 🐱 🐭 🐹

////////

Page 20: Functional Reactive Programming - RxSwift

ObservableTransforming Operators

let disposeBag = DisposeBag() Observable.of(2, 3, 4) .map { $0 * $0 } .subscribe(onNext: { print($0) }) .addDisposableTo(disposeBag)

Page 21: Functional Reactive Programming - RxSwift

Observable

let disposeBag = DisposeBag() Observable.of(2, 3, 4) .map { $0 * $0 } .subscribe(onNext: { print($0) }) .addDisposableTo(disposeBag)

4 16

2 43

9

map { $0 * $0 }

Transforming Operators

Page 22: Functional Reactive Programming - RxSwift

CombineLatest

JustFlatMapLatest

Debounce

Page 23: Functional Reactive Programming - RxSwift

rxmarble.com

Page 24: Functional Reactive Programming - RxSwift

Traditional X Reactive

Page 25: Functional Reactive Programming - RxSwift

class ElementViewController: UIViewController { @IBOutlet weak var usernameTextField: UITextField! @IBOutlet weak var passwordTextField: UITextField! @IBOutlet weak var button: UIButton! override func viewDidLoad() { button.isEnabled = false usernameTextField.delegate = self passwordTextField.delegate = self } func enableLoginButton(username: String, password: String) { button.isEnabled = (username != "" && password != "") } }

extension ElementViewController: UITextFieldDelegate { func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { // check textfield } func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { // check textfield return true }

Page 26: Functional Reactive Programming - RxSwift

class ElementViewController: UIViewController { @IBOutlet weak var usernameTextField: UITextField! @IBOutlet weak var passwordTextField: UITextField! @IBOutlet weak var button: UIButton! let disposeBag = DisposeBag() override func viewDidLoad() { super.viewDidLoad() Observable.combineLatest(usernameTextField.rx.text, passwordTextField.rx.text) { username, password in return username != "" && password != "" } .subscribe { button.isEnable = $0 } .addDisposableTo(disposeBag) }

}

Page 27: Functional Reactive Programming - RxSwift

class ElementViewController: UIViewController { @IBOutlet weak var usernameTextField: UITextField! @IBOutlet weak var passwordTextField: UITextField! @IBOutlet weak var button: UIButton! let disposeBag = DisposeBag() override func viewDidLoad() { super.viewDidLoad() Observable.combineLatest(usernameTextField.rx.text, passwordTextField.rx.text) { username, password in return username != "" && password != "" } .subscribe { button.isEnable = true } .addDisposableTo(disposeBag) }

}

class ElementViewController: UIViewController { @IBOutlet weak var usernameTextField: UITextField! @IBOutlet weak var passwordTextField: UITextField! @IBOutlet weak var button: UIButton! override func viewDidLoad() { button.isEnabled = false usernameTextField.delegate = self passwordTextField.delegate = self } func enableLoginButton(username: String, password: String) { button.isEnabled = (username != "" && password != "") } }

extension ElementViewController: UITextFieldDelegate { func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { // check textfield } func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { // check textfield return true }

40%Saving

Traditional Reactive

Page 28: Functional Reactive Programming - RxSwift

Expressivity

Page 29: Functional Reactive Programming - RxSwift

Senquence API Calls

1. Get userID 2. Get credit card account ID 3. Get credit card info

Page 30: Functional Reactive Programming - RxSwift

Alamofire.request("https://fake/login", method: .post) .responseJSON { (response) in Alamofire.request("https://fake/creaditToken", method: .post, parameters: ["creditToken": response.id]) .responseJSON { (response) in Alamofire.request("https//fake/creaditCard", method: .post, parameters: ["creditCard": response.token]) .responseJSON { // get credit card info } } }

Page 31: Functional Reactive Programming - RxSwift

class CreditCardService { func getCreditCards() { let service = [] as! Service service.rxLogin(username: "[email protected]", password: "12345") .flatMap { (authResponse) -> Observable<CreditCardAccount> in return service.rxCredidCardAccount(userId: authResponse.userId) } .flatMap { (creditCardAccount) -> Observable<[CreditCardInfo]> in return service.rxAllCreditCards(userId: creditCardAccount.cardsId) } .subscribe { (creditCardInfo) in print(creditCardInfo) } } }

Page 32: Functional Reactive Programming - RxSwift

Marvelous

Page 33: Functional Reactive Programming - RxSwift

static func request(endpoint: Resource) -> Observable<[String:AnyObject]> { return Observable.create { observer in

} return Disposables.create { request.cancel() } } }

Request Observable

Page 34: Functional Reactive Programming - RxSwift

let request = Alamofire.request(endpoint.path, method: endpoint.method, parameters: endpoint.parameter) .validate() .responseJSON { (response: DataResponse<Any>) in if let err = response.result.error { observer.onError(err) } else { if let result = response.result.value as? [String:AnyObject] { observer.onNext(result) } observer.onCompleted() }

static func request(endpoint: Resource) -> Observable<[String:AnyObject]> { return Observable.create { observer in

} return Disposables.create { request.cancel() } } }

Request Observable

Page 35: Functional Reactive Programming - RxSwift

@IBOutlet weak var searchBar: UISearchBar! @IBOutlet weak var tableView: UITableView!

// Trigger when reach the bottom of the tableView let trigger = tableView.rx.contentOffset.flatMap { _ in (self.tableView.contentOffset.y + self.tableView.frame.size.height + 20 > self.tableView.contentSize.height) ? Observable.just() : Observable.empty() }

let searchResult = searchBar.rx.text.asObservable() .debounce(3, scheduler: MainScheduler.instance) .flatMapLatest { query -> Observable<[Character]> in return CharacterAPI().heros(search: query!, trigger: trigger) }.catchErrorJustReturn([Character]())

searchResult.bindTo(tableView.rx.items(cellIdentifier: "HERO_CELL")) { row, character, herocell in let cell: HeroTableViewCell = (herocell as? HeroTableViewCell)! cell.heroNameLabel.text = character.name cell.downloadableImage = UIImage.imageFrom(urlString: character.getHeroImagePath()) }.addDisposableTo(disposeBag)

ViewController

Page 36: Functional Reactive Programming - RxSwift

Thanks• reactive.io• github.com/frelei/marvelous• gitHub.com/ReactiveX/RxSwift

[email protected]

• rxmarbles.com

• slack.rxswift.org