CocoaheadsSKG #2 - Introduction to RxSwift

5a3cfb263fe4968b76c4c0bde721f047?s=47 CocoaHeadsSKG
February 24, 2016

CocoaheadsSKG #2 - Introduction to RxSwift

@gkravas talks about reactive programming on iOS with RxSwift

5a3cfb263fe4968b76c4c0bde721f047?s=128

CocoaHeadsSKG

February 24, 2016
Tweet

Transcript

  1. RxSwift RxSwift An API for asynchronous programming with observable streams

    @gkravas 1
  2. 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
  3. 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
  4. Who is Using ReactiveX Who is Using ReactiveX 4

  5. Basic Concepts Basic Concepts Observable Operators Single Subject Scheduler 5

  6. Observable<?> Observable<?> Hot Observables Cold Observables Connectable Observables 6

  7. Operators Operators Creating Transforming Filtering Combining Error Handling Conditional and

    Boolean Mathematical and Aggregate 7
  8. 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
  9. 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
  10. 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
  11. RxSwift Specific RxSwift Specific Resources Resources Disposables & DisposableBags Disposables

    & DisposableBags Helps on memory Helps on memory management for observables management for observables 11
  12. 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
  13. 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
  14. Show us the code Show us the code 14

  15. 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<Int>*/ = Variable(1) let b /*: Observable<Int>*/ = Variable(2) let c = Observable.combineLatest(a, b) { $0 + $1 } .filter { $0 >= 0 } .map { "\($0) is positive" } .subscribeNext { print($0) } Traditional RxSwift 15
  16. UI Bindings UI Bindings // type is Observable<String> let subscription/*:

    Disposable */ = primeTextField.rx_text // type is Observable<Observable<Prime>> .map { WolframAlphaIsPrime($0.toInt() ?? 0) } // type is Observable<Prime> .concat() // type is Observable<String> .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
  17. 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
  18. Alamofire Along With RxSwift Alamofire Along With RxSwift func getSprites()

    -> Observable<AnyObject?> { 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
  19. 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
  20. 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
  21. 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
  22. Example Project Example Project https://github.com/CocoaheadsSKG/RxSwiftMapKit 22

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