Functional Reactive Programming - RxSwift
-
Upload
rodrigo-leite -
Category
Software
-
view
220 -
download
8
Transcript of Functional Reactive Programming - RxSwift
![Page 1: Functional Reactive Programming - RxSwift](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/1.jpg)
Functional Reactive Programming
![Page 3: Functional Reactive Programming - RxSwift](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/3.jpg)
Focus on mobile development
OutsourcingProduct Development
![Page 4: Functional Reactive Programming - RxSwift](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/4.jpg)
![Page 5: Functional Reactive Programming - RxSwift](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/5.jpg)
Functional & Reactive
![Page 6: Functional Reactive Programming - RxSwift](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/6.jpg)
Functional &Avoid state
Immutable dataDeclarative programming
![Page 7: Functional Reactive Programming - RxSwift](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/7.jpg)
& Reactive
Data drivenValues over time
Streams
![Page 8: Functional Reactive Programming - RxSwift](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/8.jpg)
Reactive Cocoa RxSwift
![Page 9: Functional Reactive Programming - RxSwift](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/9.jpg)
RxSwift
Based on ReactiveX
![Page 10: Functional Reactive Programming - RxSwift](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/10.jpg)
RxSwift
Based on ReactiveX
Observable pattern
Iterator pattern}Functional programming
} Reactive
![Page 11: Functional Reactive Programming - RxSwift](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/11.jpg)
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](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/12.jpg)
ObservableEmits events over time
ObserverSubscribe to listen events emitted by the observable
![Page 13: Functional Reactive Programming - RxSwift](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/13.jpg)
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](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/14.jpg)
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](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/15.jpg)
ObservableEmits events over time
Array<T>
Observable<T>
![Page 16: Functional Reactive Programming - RxSwift](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/16.jpg)
ObservableCreate Operator
let observable = Observable.just("Hello World")
![Page 17: Functional Reactive Programming - RxSwift](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/17.jpg)
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](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/18.jpg)
ObservableCreate Operator
let disposeBag = DisposeBag() Observable.from(["🐶", "🐱", "🐭", "🐹"]) .subscribe(onNext: { print($0) }) .addDisposableTo(disposeBag)
![Page 19: Functional Reactive Programming - RxSwift](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/19.jpg)
ObservableCreate Operator
let disposeBag = DisposeBag() Observable.from(["🐶", "🐱", "🐭", "🐹"]) .subscribe(onNext: { print($0) }) .addDisposableTo(disposeBag)
🐶 🐱 🐭 🐹
🐶 🐱 🐭 🐹
////////
![Page 20: Functional Reactive Programming - RxSwift](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/20.jpg)
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](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/21.jpg)
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](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/22.jpg)
CombineLatest
JustFlatMapLatest
Debounce
![Page 24: Functional Reactive Programming - RxSwift](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/24.jpg)
Traditional X Reactive
![Page 25: Functional Reactive Programming - RxSwift](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/25.jpg)
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](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/26.jpg)
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](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/27.jpg)
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](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/28.jpg)
Expressivity
![Page 29: Functional Reactive Programming - RxSwift](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/29.jpg)
Senquence API Calls
1. Get userID 2. Get credit card account ID 3. Get credit card info
![Page 30: Functional Reactive Programming - RxSwift](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/30.jpg)
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](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/31.jpg)
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](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/32.jpg)
Marvelous
![Page 33: Functional Reactive Programming - RxSwift](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/33.jpg)
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](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/34.jpg)
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](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/35.jpg)
@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](https://reader034.fdocuments.net/reader034/viewer/2022052305/58729f191a28ab07208b55cd/html5/thumbnails/36.jpg)
Thanks• reactive.io• github.com/frelei/marvelous• gitHub.com/ReactiveX/RxSwift
• rxmarbles.com
• slack.rxswift.org