使用Alamofire 4,我们有一个API响应验证器,我们调用如下:
func request<Endpoint: APIEndpoint>(_ baseURL: URL, endpoint: Endpoint, completion: @escaping (_ object: Endpoint.ResponseType?, _ error: AFError?) -> Void) -> DataRequest where Endpoint.ResponseType: Codable {
let responseSerializer = APIObjectResponseSerializer(endpoint)
let request = self.request(baseURL, endpoint: endpoint)
.validate(APIResponseValidator.validate) << VALIDATOR PASSED HERE
.response(responseSerializer: responseSerializer) { response in
completion(response.value, response.error)
}
return request
}
它看起来像这样:
static func validate(request: URLRequest?, response: HTTPURLResponse, data: Data?) -> Request.ValidationResult {
// **INSERT OTHER FAILURE CHECKS HERE**
// Verify server time is within a valid time window.
let headers = response.allHeaderFields
guard let serverTimeString = headers["Date"] as? String, let serverTime = DateUtils.headerDateFormatter().date(from: serverTimeString) else {
Log.error("APIValidation: no Date in response header")
return .failure(APIError.appTimeSettingInvalid))
}
// **INSERT OTHER FAILURE CHECKS HERE**
return .success(Void())
}
适当的错误将使其返回到请求完成处理程序
▿ APIError
▿ appTimeSettingInvalid
我们可以用正确的错误更新UI,每个人都很高兴。
但现在有了Alamofire,它就是:
▿ Optional<Error>
▿ some : AFError
▿ requestRetryFailed : 2 elements
▿ retryError : AFError
▿ responseValidationFailed : 1 element
▿ reason : ResponseValidationFailureReason
▿ customValidationFailed : 1 element
▿ error : APIError
▿ appTimeSettingInvalid << Original custom error
▿ originalError : AFError
▿ responseValidationFailed : 1 element
▿ reason : ResponseValidationFailureReason
▿ customValidationFailed : 1 element
▿ error : APIError
▿ appTimeSettingInvalid << Original custom error
我需要这样访问:
if let underlyingError = (error as? AFError)?.underlyingError as? AFError,
case let AFError.requestRetryFailed(_, originalError) = underlyingError,
case let AFError.responseValidationFailed(reason) = originalError,
case let .customValidationFailed(initialCustomError) = reason {
showAlert(initialCustomError)
}
这似乎很荒谬。我错过了什么?为什么自定义验证在方法没有任何变化的情况下失败了,为什么它被一层其他错误包裹着?当验证将以同样的方式失败时,为什么要重试请求?
如何在所有请求中一致地返回自定义错误
在Alamofire 5中,返回的所有错误都包含在AFError
实例中,包括自定义验证错误。这允许我们的Response
类型包含类型化错误,并提供一致的错误类型。然而,不幸的是,验证API仍然返回Error
实例,因此需要剥离额外的层。您可以使用方便的asAFError
属性来执行强制转换,使用underlyingError
属性来获取任何潜在的错误。使用switch
语句也可以使提取更容易。您还可以对响应执行mapError
,以提取所需的特定错误类型。
至于重试,很可能您的重试器没有更新以提取错误,因此您的自定义错误类型可以适当地避免重试。
将AFError转换为普通自定义错误的代码示例错误:
像往常一样,在结果类型上使用开关,然后在错误上使用:
{ (result) in
switch result {
case .success(_, _, _):
,.............
case .failure(let error):
let afError = error.asAFError?.underlyingError ?? error
completion(afError)
asAF错误?。underlyingError在Alomafire框架中可用。