メルカリアッテのRxSwift実装ガイド

5fa286b095b15f7572bb5c16186d2ffe?s=47 yohei okada
October 11, 2017

 メルカリアッテのRxSwift実装ガイド

メルカリアッテで採用している実装ガイド

5fa286b095b15f7572bb5c16186d2ffe?s=128

yohei okada

October 11, 2017
Tweet

Transcript

  1. ϝϧΧϦΞοςͷ RxSwift࣮૷ΨΠυ Souzoh iOS Talk 2017 Oct 11 1

  2. ࣗݾ঺հ • Ԭా༸ฏ(@parakeety) • 2017 Jan 1ೖࣾ • ϝϧΧϦ ΞοςͷiOSΞϓϦΛ։ൃ

    2
  3. ϝϧΧϦ Ξος • ։ൃ౰ॳ͔ΒRxSwiftΛ࠾༻ • ৭ʑࢼߦࡨޡ͠ͳ͕Β࣮૷ํ਑Λ໛ࡧ • ࠷ۙ͸େ͖ͳ໰୊ʹૺ۰͢Δࣄ΋ͳ͘ɺ͋Δఔ౓ํ਑͕ݻ·͖ͬͯͨ 3

  4. RxSwiftΛ༻͍ͨ։ൃ ϝϧΧϦ ΞοςͰ༻͍͍ͯΔ࣮૷ΨΠυͷҰ ෦Λ঺հ 4

  5. ͓͠ͳ͕͖ 1. ViewModelͷ࣮૷ΨΠυ 2. Error Handling 5

  6. ϝϧΧϦ ΞοςͷΞʔΩςΫνϟ • Model + View + ViewController + ViewModel

    • ViewControllerΛεϦϜʹอͭͷͱɺςετ͢ΔͨΊʹ ViewModelʹॲཧΛू໿ • ViewController͸ViewModelͱ1ର1ͷؔ܎ 6
  7. 1. ViewModel࣮૷ΨΠυ private var viewModel: ViewModel! private let refreshTrigger =

    PublishSubject<Void>() // view model΁ͷinput override func viewDidLoad() { super.viewDidLoad() viewModel = ViewModel(refreshTrigger: refreshTrigger.asDriver()) } 7 1. ViewModel΁ͷinput͸ViewModelͷinitializerͰશͯ౉͢
  8. 1. ViewModel࣮૷ΨΠυ class ViewModel { let offers: Driver<[Offer]> // view

    model͔Βͷoutput init(refreshTrigger: Driver<Void>) { offers = refreshTrigger.flatMap { _ in return APIClient.shared.responseFrom(SomeRequest) } } } 8 2. ViewModel͔Βͷoutput͸ViewModelͷpropertyͱͯ͠ఆٛ
  9. 1. ViewModel࣮૷ΨΠυ override func viewDidLoad() { super.viewDidLoad() viewModel = ViewModel(refreshTrigger:

    refreshTrigger.asDriver()) viewModel.offers .drive() .disposed(by: disposeBag) } 9
  10. 1. ViewModel࣮૷ΨΠυ 3. ViewModel΁ͷinput΋output΋DriverΛ࢖͏ - observableʹ஋͕ྲྀΕͯ͘Δͷ͕ઌ͔ɺsubscribe͕ઌ͔Ͱҙਤ͠ͳ͍ಈ ࡞͕ൃੜ͢Δ͜ͱ͕͋ͬͨ(subscribe͔ͯ͠Β஋͕ྲྀΕͯ͘Ε͹஋Λड͚ औΕΔ͕ɺ஋͕ྲྀΕ͖ͯͨޙʹsubscribeͯ͠΋஋Λड͚औΕͳ͍) - subscribeͷλΠϛϯά΍ॱ൪Λؾʹ͠ͳͯ͘΋ྑ͍Α͏ʹɺsubscribe͠

    ͨ࣌ʹreplayͤ͞ΔΑ͏ʹͨ͠ 10
  11. 1. ViewModel࣮૷ΨΠυ 1. ViewModel΁ͷinput͸ViewModelͷinitializerͰશͯ౉͢ 2. ViewModel͔Βͷoutput͸ViewModelͷpropertyͱͯ͠ఆٛ͢Δ 3. ViewModel΁ͷinput΋output΋DriverΛ࢖͏ 11 ·ͱΊ

  12. 2. Error Handling αʔόʔʹϦΫΤετΛ౤͛ͯɺΤϥʔ͕ฦ͖ͬͯͨ ࣌ʹɺϢʔβʔʹΤϥʔϝοηʔδΛද͍ࣔͨ͠ 12

  13. 2. Error Handling observableʹerror͕ྲྀΕΔͱobservable͕ऴྃͯ͠͠ ·͏ => ΋͏Ұ౓subscribe͠௚͞ͳ͍ͱ͍͚ͳ͍ 13

  14. 2. Error Handling ਖ਼ৗܥͱΤϥʔͷstreamΛ෼཭͢Δ 14

  15. 2. Error Handling enum Result<Response> { case succeeded(Response) case failed(Error)

    } extension ObservableConvertibleType { func resultDriver() -> Driver<Result<E>> { return self.asObservable() .map { Result.succeeded($0) } .asDriver { Driver.just(Result.failed($0)) } } } 15
  16. 2. Errorͷऔѻ͍ extension SharedSequence { static func split(result: Driver<Result<Response>>) ->

    (response: Driver<Response>, error: Driver<Error>) { let responseDriver = result.flatMap { result -> Driver<Response> in switch result { case .succeeded(let response): return Driver.just(response) case .failed: return Driver.empty() } } let errorDriver = result.flatMap { result -> Driver<Error> in switch result { case .succeeded: return Driver.empty() case .failed(let error): return Driver.just(error) } } return (responseDriver, errorDriver) } } 16
  17. 2. Errorͷऔѻ͍ let responseDriver = result.flatMap { result -> Driver<Response>

    in switch result { case .succeeded(let response): return Driver.just(response) case .failed: return Driver.empty() } } 17
  18. 2. Errorͷऔѻ͍ let errorDriver = result.flatMap { result -> Driver<Error>

    in switch result { case .succeeded: return Driver.empty() case .failed(let error): return Driver.just(error) } } 18
  19. 2. Errorͷऔѻ͍ extension SharedSequence { static func split(result: Driver<Result<Response>>) ->

    (response: Driver<Response>, error: Driver<Error>) { let responseDriver = result.flatMap { result -> Driver<Response> in switch result { case .succeeded(let response): return Driver.just(response) case .failed: return Driver.empty() } } let errorDriver = result.flatMap { result -> Driver<Error> in switch result { case .succeeded: return Driver.empty() case .failed(let error): return Driver.just(error) } } return (responseDriver, errorDriver) } } 19
  20. 2. Errorͷऔѻ͍ class ViewModel { let offers: Driver<[Offer]> let error:

    Driver<Error> init(refreshTrigger: Driver<Void>) { let offerResult: Driver<Result<[Offer]>> = refreshTrigger .flatMap { _ in return APIClient.shared.responseFrom(OfferRequest) .resultDriver() } (offers, error) = Driver.split(result: offerResult) } } 20 ࢖͏ଆ(ViewModel)
  21. 2. Errorͷऔѻ͍ class ViewController: UIViewController { private var viewModel: ViewModel!

    private let refreshTrigger = PublishSubject<Void>() private let disposeBag = DisposeBag() override func viewDidLoad() { super.viewDidLoad() viewModel = ViewModel(refreshTrigger: refreshTrigger) viewModel.offers .drive() .disposed(by: disposeBag) viewModel.error .drive() // handle error i.e) show alert .disposed(by: disposeBag) } } 21 ࢖͏ଆ(ViewController)
  22. ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ 22