RxSwift + обработка ошибок пользовательского картографа Alamofire - PullRequest
0 голосов
/ 14 октября 2019

RxSwift еще один вопрос об обработке ошибок:

Я использую Alamofire + RxAlamofire следующим образом:

SessionManager.default.rx.responseJSON(.post, url, parameters:params)

пример:

func login() -> Observable<Int> {
    let urlString = ...
    let params = ...
    return SessionManager.default.rx.responseJSON(.post, url, parameters:params)
        .rxJsonDefaultResponse()
        .map({ (data) in
            data["clientId"] as! Int
        })
}
....

extension ObservableType where Element == (HTTPURLResponse, Any) {

    func rxJsonDefaultResponse() -> Observable<Dictionary<String, Any>> {

        return self.asObservable().map { data -> Dictionary<String, Any> in

            if... //error chechings
                    throw NSError(domain: ..,
                                  code: ...,
                                  userInfo: ...)
            }
            ...
            return json
        }
    }
}

используя:

loginBtn.rx.tap
.flatMap{ _ in
    provider.login()
}.subscribe(onNext: { id in
       ... 
    }, onError: { (er) in
        ErrorPresentationHelper.showErrorAlert(for: er)
    })
.disposed(by: bag)

Таким образом, если произошла ошибка, все работает, как задумано: предупреждение об ошибке показывает и 'loginBtn.rx.tap' удален, но мне нужно, чтобы он был еще жив, какова моя стратегия, если я хочу использовать блок onError

1 Ответ

0 голосов
/ 14 октября 2019

Вы можете использовать функцию материализовать в rxSwift. Он преобразует любое Наблюдаемое в Наблюдаемое своих событий. Так что вы будете слушать Observable<Event<Int>>, чем Observable<Int>. Любая ошибка, выброшенная из плоской карты, будет зафиксирована как событие ошибки в onNext вашего блока подписки и может быть обработана там. И ваша подписка все равно будет жива. Пример кода будет следующим.

        button.rx.tap.flatMap { _ in
            return Observable.just(0)
            .flatMap { _ -> Observable<Int> in
                provider.login()
            }.materialize()
        }.subscribe(onNext: { event in
            switch event {
            case .next:
                if let value = event.element {
                    print(value) //You will be getting your value here
                }
            case .error:
                if let error = event.error {
                    print(error.localizedDescription) //You will be getting your captured error here
                }
            case .completed:
                print("Subscription completed")
            }
        }) {
            print("Subscription disposed")
        }.disposed(by: disposeBag)

Надеюсь, это поможет. Вы можете оформить расширение здесь .

...