πŸ“ RxSwift | Error Handling, Custom Extension λ§Œλ“€κΈ°

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 μ—μ„œλ„ λ¬Όλ‘  κ°€λŠ₯ !

λ‹΅κΈ€ 남기기

μ•„λž˜ ν•­λͺ©μ„ μ±„μš°κ±°λ‚˜ 였λ₯Έμͺ½ μ•„μ΄μ½˜ 쀑 ν•˜λ‚˜λ₯Ό ν΄λ¦­ν•˜μ—¬ 둜그 인 ν•˜μ„Έμš”:

WordPress.com 둜고

WordPress.com의 계정을 μ‚¬μš©ν•˜μ—¬ λŒ“κΈ€μ„ λ‚¨κΉλ‹ˆλ‹€. λ‘œκ·Έμ•„μ›ƒ /  λ³€κ²½ )

Google photo

Google의 계정을 μ‚¬μš©ν•˜μ—¬ λŒ“κΈ€μ„ λ‚¨κΉλ‹ˆλ‹€. λ‘œκ·Έμ•„μ›ƒ /  λ³€κ²½ )

Twitter 사진

Twitter의 계정을 μ‚¬μš©ν•˜μ—¬ λŒ“κΈ€μ„ λ‚¨κΉλ‹ˆλ‹€. λ‘œκ·Έμ•„μ›ƒ /  λ³€κ²½ )

Facebook 사진

Facebook의 계정을 μ‚¬μš©ν•˜μ—¬ λŒ“κΈ€μ„ λ‚¨κΉλ‹ˆλ‹€. λ‘œκ·Έμ•„μ›ƒ /  λ³€κ²½ )

%s에 μ—°κ²°ν•˜λŠ” 쀑