Upgrade to Pro — share decks privately, control downloads, hide ads and more …

CocoaheadsSKG #2 - Introduction to RxSwift

CocoaHeadsSKG
February 24, 2016

CocoaheadsSKG #2 - Introduction to RxSwift

@gkravas talks about reactive programming on iOS with RxSwift

CocoaHeadsSKG

February 24, 2016
Tweet

More Decks by CocoaHeadsSKG

Other Decks in Technology

Transcript

  1. 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
  2. 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
  3. 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
  4. 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
  5. 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
  6. RxSwift Specific RxSwift Specific Resources Resources Disposables & DisposableBags Disposables

    & DisposableBags Helps on memory Helps on memory management for observables management for observables 11
  7. 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
  8. 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
  9. 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
  10. 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
  11. 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
  12. 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
  13. 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
  14. 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
  15. 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