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
}
}
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