Casting Moya Response error to defined type

☆樱花仙子☆ 提交于 2019-12-11 19:28:17

问题


I am using RxMoya for my networking calls and extending PremitiveSequence and Response so as to handle the error coming back. I declared a struct of Networking error which I could use to get all the error details and as such Pass the error message via the BaseResponse Model. Here is my NetwokingError struct

public struct NetworkingError: Error {
    let httpResponse: HTTPURLResponse?
    let networkData: Data?
    let baseError: Error
}

For my coding, I have extended the primitive sequence as follows

public extension PrimitiveSequence where TraitType == SingleTrait,

ElementType == Response {

    func mapObject<T: Codable>(_ type: T.Type, path: String? = nil) -> Single<T> {
        return flatMap { response -> Single<T> in
            return Single.just(try response.mapObject(type, path: path))
        }
    }

    func mapArray<T: Codable>(_ type: T.Type, path: String? = nil) -> Single<[T]> {
        return flatMap { response -> Single<[T]> in
            return Single.just(try response.mapArray(type, path: path))
        }
    }

    func filterSuccess() -> Single<E> {
        return flatMap { (response) -> Single<E> in
            if 200 ... 299 ~= response.statusCode {
                return Single.just(response)
            }

            print("THIS ERROR JSON jsonObject2 xx mm \(response.data)")

            do {
                let jsonObject2 = try JSONSerialization.jsonObject(with: response.getJsonData(), options: .allowFragments)
                print("THIS ERROR JSON jsonObject2 xx \(jsonObject2)")
                let jsonObject = try JSONSerialization.jsonObject(with: response.getJsonData(), options: .allowFragments) as? NetworkingError

                print("THIS ERROR JSON  xx \(jsonObject)")
                return Single.error(jsonObject ?? NetworkingError.self as! Error)
            }
        }
    }
}

if I run this code here, The app crashes return Single.error(jsonObject ?? NetworkingError.self as! Error)

in my code, I am passing data like

func postVerifyApp(challenge: Int, identifier: String) -> Observable<AuthResponse> {

        return provider.rx.request(.postVerifyApp(challenge: challenge, identifier: identifier))

            .filterSuccess()
            .mapObject(AuthResponse.self)
            .asObservable()
            .flatMap({ authResponse -> Observable<AuthResponse> in
                return self.sendTokenToServer(authResponse)
            })
    }

then I am working with this in my presenter class like this

func postVerifyApp(challenge: Int, identifier: String) {
        view?.setProgress(enabled: true)
        source.postVerifyApp(challenge: challenge, identifier: identifier)
            .retry(.delayed(maxCount: 2, time: 2.5), shouldRetry: networkRetryPredicate)
            .asSingle()
            .subscribe(onSuccess: { [weak self] response in
                guard let presenter = self, let view = presenter.view else {return}
                view.setProgress(enabled: false)
                log(response, .json)
                guard let data = response.data else {
                    return }

                view.showVerifySuccess()
                }, onError: { [weak self] error in
                    guard let presenter = self, let view = presenter.view else {return}
                    print("MESSAGE X \(error.localizedDescription)")
                    if let error = error as? NetworkingError {
                        print("MESSAGE X httpResponse \(error.httpResponse)")
                    }
                    view.setProgress(enabled: false)

            }).disposed(by: disposeBag)
    }

I want to be able to pass this Error and extract the error message and passing it to the console.

This is what my base Model looks like

struct ResponseBase<T: Codable>: Codable {
    var error: Bool?
    var message: String?
    var data: T

    var isSucessful: Bool {
        return error == false
    }

}

回答1:


The expression used to construct the Single.error can not cast as Error. Firstly, you are trying to cast a jsonObject (a Dictionary) as Error. On the right hand, on the ifNull expression, you are trying to cast a metatype (Networking.Type) as an Error.

To solve your casting problem you can use this modified NetworkingError.

public struct NetworkingError: Error {

    let httpResponse: HTTPURLResponse?
    let networkData: Data?
    let baseError: MoyaError

    init(_ response:Response) {
        self.baseError = MoyaError.statusCode(response)
        self.httpResponse = response.response
        self.networkData = response.data
    }

    func getLocalizedDescription() -> String {

       return self.baseError.localizedDescription
    }
}

Having this, modify the closure in the filterSuccess to create the NetworkingError object, passing it the Response, just like this:

func filterSuccess() -> Single<E> {
    return flatMap {
        (response) -> Single<E> in
        if 200 ... 299 ~= response.statusCode {
           return Single.just(response)
        } else {
           let netError = NetworkingError(response)
           return Single.error(netError)
        }
    }
}

I encourage you to take a look at the MoyaError definition



来源:https://stackoverflow.com/questions/57724910/casting-moya-response-error-to-defined-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!