Thanks to @fimuxd π€
https://github.com/ReactiveX/RxSwift
https://github.com/fimuxd/RxSwift
Section IV: Intermediaate RxSwift/RxCocoa
μλ¬κ΄λ¦¬
RxSwift μμ μλ¬κ΄λ¦¬λ νλ μμν¬ μ€ νλ. (= μ 곡ν΄μ€λ€.)
ν΄κ²° λ°©λ²μ catchμ retry. λ κ°μ§ λ°©λ².
– catch : defaultValue λ‘ error 볡ꡬ
– retry : μ νμ λλ 무μ νμΌλ‘ μ¬μλ
catch
– Swiftμ do-try-catch μ λΉμ·.
1. func catchError(_ handler:) -> RxSwift.Observable
– Errorκ° λ°μνλ©΄ Errorκ° λ°μνκΈ° μ μ κ°μ λ°ν.
2. func catchErrorJustReturn(_ element:) -> RxSwift.Observable
– Errorλ₯Ό 무μνκ³ μ΄μ μ μ μΈν΄λ κ°μ λ°ν.
– Errorμ λ΄μ©μ μκ΄μμ΄ λͺ¨λ μλ¬μ λν΄ λμΌν κ°μ΄ λ°νλλ€. 1.μ λΉν΄μ μ νμ .
μ¬μ©
– μλ¬λ Sequenceκ° μ§νλλ κ³Όμ μμ λ°μνλ€. μλ¬κ° λ°μνμ λ λ³λμ μ²λ¦¬κ° μλ€λ©΄ κ·Έλλ‘ μ μ§λκ³ μ¬μ©μμκ² Errorκ° μ λ¬λκ² λλ€.
let weather = cityNameTextField.rx.controlEvent(.editingDidEndOnExit) .asObservable() .map { [weak self] in self?.cityNameTextField.text } .filter { ($0 ?? "").count > 0 } .flatMapLatest { APIClient.shared.requestWeather(city: $0!) } .catchError { [weak self] error in // π« if let currentWeather = self?.currentWeather { return Observable.just(currentWeather) } else { return Observable.just(Weather.empty) } }
retry
– sequence μμ λ°μν μλ¬μμ retry κ° μ¬μ©λλ©΄ sequenceλ μ€μ€λ‘λ₯Ό κ³μ λ°λ³΅νλ€.
– μ μ κ° μ§μ μ¬μλν λμ λΆμμ©μ λ§κΈ° μν΄μ κΆμ₯λλ λ°©λ². (λ€νΈμν¬ μλ¬μ κ²½μ° νμ© κ°λ₯!)
let weather = cityNameTextField.rx.controlEvent(.editingDidEndOnExit) .asObservable() .map { [weak self] in self?.cityNameTextField.text } .filter { ($0 ?? "").count > 0 } .flatMapLatest { APIClient.shared.requestWeather(city: $0!) } .retry(3) // π« .catchError { [weak self] error in if let currentWeather = self?.currentWeather { return Observable.just(currentWeather) } else { return Observable.just(Weather.empty) } }
– .retryWhen
– νΉμ ν μλ¬μΌ λμ retry 쑰건μ μ μν μ μλ€.
Custom Error
enum APIError { case serverError case unknowError } func testError(session: URLSession, request: URLRequest) { session.rx.response(request: request).map { response, data in if 200 ..< 300 ~= response.statusCode { return try JSON(data) } else if 400 ..< 500 ~= response.statusCode { throw APIError.serverError } else { throw APIError.unknowError } } }
Creating Custom Reactive Extensions
extension Reactive where Base: URLSession { func response(request: URLRequest) -> Observable<(HTTPURLResponse, Data)> { Observable.create { observer in let task = self.base.dataTask(with: request) { data, response, error in guard let response = response, let data = data else { observer.on(.error(error ?? RxCocoaURLError.unknown)) return } guard let httpResponse = response as? HTTPURLResponse else { observer.on(.error(RxCocoaURLError.nonHTTPResponse(response: response))) return } observer.onNext((httpResponse, data)) observer.on(.completed) } task.resume() return Disposables.create(with: task.cancel) } } }
– Reactive extension μ νλ‘ν μ½ extension.
– .rx λ₯Ό URLSession λ€μ λΆμΌ μ μκ² ν΄μ€λ€.
– μ½λ μμμλ URLSession μ΄μ§λ§ λ€λ₯Έ class μμλ λ¬Όλ‘ κ°λ₯ !