【问题标题】:Custom validation error no longer working in Alamofire 5自定义验证错误不再在 Alamofire 5 中起作用
【发布时间】:2020-11-16 00:28:35
【问题描述】:

使用 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)
}

这似乎很荒谬。我错过了什么?当方法没有任何改变时,为什么自定义验证会失败,为什么它会被包裹在一层其他错误中?当验证将以同样的方式失败时,为什么要重试请求?

如何在所有请求中始终如一地恢复我的自定义错误?

【问题讨论】:

    标签: swift xcode alamofire alamofire5


    【解决方案1】:

    在 Alamofire 5 中,返回的所有错误都包含在 AFError 实例中,包括自定义验证错误。这允许我们的Response 类型包含类型错误并提供一致的错误类型。但是,不幸的是,验证 API 仍然返回 Error 实例,因此还有一个额外的层需要剥离。您可以使用方便的asAFError 属性执行强制转换,并使用underlyingError 属性来获取任何潜在错误。使用switch 语句也可以使提取更容易。您还可以在回复上mapError 以提取您想要的特定错误类型。

    至于重试,很可能您的重试器尚未更新以提取错误,因此您的自定义错误类型可以正确避免重试。

    【讨论】:

    • 当然,我们会在 Alamofire 6 上看看它。
    猜你喜欢
    • 2017-01-26
    • 2021-01-06
    • 2021-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-14
    相关资源
    最近更新 更多