Slide 1

Slide 1 text

RxSwift RxSwift An API for asynchronous programming with observable streams @gkravas 1

Slide 2

Slide 2 text

What is ReactiveX What is ReactiveX The Observer pattern done right. The Observer pattern done right. ReactiveX is a combination ReactiveX is a combination of the best ideas of the best ideas from the from the Observer Observer pattern, pattern, the the Iterator Iterator pattern, pattern, and and functional programming functional programming 2

Slide 3

Slide 3 text

Functional Avoid intricate stateful programs, using clean input/output functions over observable streams. Less is more ReactiveX's operators often reduce what was once an elaborate challenge into a few lines of code. Async error handling Traditional try/catch is powerless for errors in asynchronous computations, but ReactiveX is equipped with proper mechanisms for handling errors. Concurrency made easy Observables and Schedulers in ReactiveX allow the programmer to abstract away low-level threading, synchronization, and concurrency issues. Features Features 3

Slide 4

Slide 4 text

Who is Using ReactiveX Who is Using ReactiveX 4

Slide 5

Slide 5 text

Basic Concepts Basic Concepts Observable Operators Single Subject Scheduler 5

Slide 6

Slide 6 text

Observable Observable Hot Observables Cold Observables Connectable Observables 6

Slide 7

Slide 7 text

Operators Operators Creating Transforming Filtering Combining Error Handling Conditional and Boolean Mathematical and Aggregate 7

Slide 8

Slide 8 text

Single Single Rx Java only feature It emmits only one value instead of a series. Instead of observable.subscibe (onNext, onErro r, and onCompleted) we can use observable.subscribe(onSuccess, onFail) 8

Slide 9

Slide 9 text

Subject Subject Work both ways Acts like a proxy converting "hot" to "cold" and vice versa AsyncSubject (emits last set of items) BehaviorSubject (emits most recent and beyond) PublishSubject (emits only source's) ReplaySubject (emits everything) Types Types 9

Slide 10

Slide 10 text

Scheduler Scheduler Used for multithreading Gives the ability to change threads during a sequence CurrentThreadScheduler (Serial scheduler) MainScheduler (Serial scheduler) SerialDispatchQueueScheduler (Serial scheduler) ConcurrentDispatchQueueScheduler (Concurrent scheduler) OperationQueueScheduler (Concurrent scheduler) Types Types 10

Slide 11

Slide 11 text

RxSwift Specific RxSwift Specific Resources Resources Disposables & DisposableBags Disposables & DisposableBags Helps on memory Helps on memory management for observables management for observables 11

Slide 12

Slide 12 text

Testing(RxBlocking) Testing(RxBlocking) To test observables we To test observables we need to convert them from need to convert them from async to sync async to sync (non blocking to blocking) (non blocking to blocking) 12

Slide 13

Slide 13 text

RxSwift Setup RxSwift Setup # Podfile use_frameworks! pod 'RxSwift', '~> 2.2' pod 'RxCocoa', '~> 2.2' pod 'RxBlocking', '~> 2.2' pod 'RxTests', '~> 2.2' Cocoa pods Cocoa pods 13

Slide 14

Slide 14 text

Show us the code Show us the code 14

Slide 15

Slide 15 text

Calculated Variables Calculated Variables var c: String var a = 1 var b = 2 if a + b >= 0 { c = "\(a + b) is positive" } let a /*: Observable*/ = Variable(1) let b /*: Observable*/ = Variable(2) let c = Observable.combineLatest(a, b) { $0 + $1 } .filter { $0 >= 0 } .map { "\($0) is positive" } .subscribeNext { print($0) } Traditional RxSwift 15

Slide 16

Slide 16 text

UI Bindings UI Bindings // type is Observable let subscription/*: Disposable */ = primeTextField.rx_text // type is Observable> .map { WolframAlphaIsPrime($0.toInt() ?? 0) } // type is Observable .concat() // type is Observable .map { "number \($0.n) is prime? \($0.isPrime)" } // return Disposable that can be used to unbind everything .bindTo(resultLabel.rx_text) .addDisposableTo(disposableBag) // This will set resultLabel.text to "number 43 is prime? true" after // server call completes. primeTextField.text = "43" 16

Slide 17

Slide 17 text

KVO(Key-Value Observing) KVO(Key-Value Observing) view .rx_observe(CGRect.self, "frame") .subscribeNext { frame in ... } or view .rx_observeWeakly(CGRect.self, "frame") .subscribeNext { frame in ... } 17

Slide 18

Slide 18 text

Alamofire Along With RxSwift Alamofire Along With RxSwift func getSprites() -> Observable { return create{ observer in var request = Alamofire .request(.GET, "https://epoquecore.com/sprites", parameters: nil) .response({ (request, response, data, error) in if(error != nil){ sendError(observer, error!); } else { sendNext(observer, data); sendCompleted(observer); } }); return AnonymousDisposable { request.cancel() } } } Or you can use RxAlamofire 18

Slide 19

Slide 19 text

Altering Images on The Fly Altering Images on The Fly let imageSubscription = imageURLs .throttle(0.2, scheduler: MainScheduler.instance) .flatMapLatest { imageURL in API.fetchImage(imageURL) } .observeOn(operationScheduler) .map { imageData in return decodeAndBlurImage(imageData) } .observeOn(MainScheduler.instance) .subscribeNext { blurredImage in imageView.image = blurredImage } .addDisposableTo(disposableBag) 19

Slide 20

Slide 20 text

Field Validation Field Validation let usernameValid = usernameOutlet.rx_text .map { $0.characters.count >= minimalUsernameLength } .shareReplay(1) // without this map would be executed once //for each binding, rx is stateless by default let passwordValid = passwordOutlet.rx_text .map { $0.characters.count >= minimalPasswordLength } .shareReplay(1) let everythingValid = Observable.combineLatest(usernameValid, passwordValid) { $0 && $1 } .shareReplay(1) usernameValid .bindTo(passwordOutlet.rx_enabled) .addDisposableTo(disposeBag) usernameValid .bindTo(usernameValidOutlet.rx_hidden) .addDisposableTo(disposeBag) passwordValid .bindTo(passwordValidOutlet.rx_hidden) .addDisposableTo(disposeBag) everythingValid .bindTo(doSomethingOutlet.rx_enabled) .addDisposableTo(disposeBag) doSomethingOutlet.rx_tap .subscribeNext { [weak self] in self?.showAlert() } .addDisposableTo(disposeBag) 20

Slide 21

Slide 21 text

Error Handling Error Handling getApi() // Set 3 attempts to get response .retry(3) // Set 2 seconds timeout .timeout(2, mainScheduler) // Subscribe in background thread .subscribeOn(backgroundWorkScheduler) // Observe in main thread .observeOn(mainScheduler) // Subscribe on observer .subscribe( onNext: { data in do { let post = try NSJSONSerialization.JSONObjectWithData(data as! NSData, options: []) as! NSDictionary print(post) } catch { print(NSString(data: data as! NSData, encoding: NSUTF8StringEncoding)) return } }, onError: { error in print(error) }, onCompleted: { print("Completed") }, onDisposed: { print("Disposed") } ) .addDisposableTo(disposeBag) 21

Slide 22

Slide 22 text

Example Project Example Project https://github.com/CocoaheadsSKG/RxSwiftMapKit 22

Slide 23

Slide 23 text

Thank You :) Thank You :) Questions? Questions? 23