Пользовательская ошибка проверки больше не работает в Alamofire 5

Используя 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

и мы могли обновить пользовательский интерфейс с правильной ошибкой, все были довольны.

Но теперь с 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)
}

Это кажется абсурдным. Что мне не хватает? Почему пользовательская проверка завершилась неудачно, если в методе ничего не изменилось, и почему он заключен в слой других ошибок? Зачем повторять запрос, если проверка не удастся точно так же?

Как мне последовательно возвращать мою пользовательскую ошибку во всех моих запросах?

2 ответа

Решение

В Alamofire 5 все ошибки возвращаются, содержащиеся в AFErrorэкземпляр, включая пользовательские ошибки проверки. Это позволяет нашимResponseтипы, содержащие типизированные ошибки и обеспечивающие согласованный тип ошибки. Однако API проверки по-прежнему возвращаетErrorэкземпляров, к сожалению, поэтому есть дополнительный слой, который нужно отклеить. Вы можете использовать удобствоasAFError свойство для выполнения приведения и underlyingErrorсвойство, чтобы захватить любые основные ошибки. Использованиеswitchоператоры также могут облегчить извлечение. Вы также можетеmapError в ответах для извлечения нужных вам типов ошибок.

Что касается повтора, вероятно, ваш retrier не был обновлен для извлечения ошибок таким образом, чтобы повторные попытки должным образом избегались с вашим пользовательским типом ошибки.

Пример кода для преобразования AFError в обычную пользовательскую ошибку:

Как обычно, используйте переключатель типа результата, затем при ошибке:

      { (result) in
    switch result {
    case .success(_, _, _):
   ,.............
     case .failure(let error):
     let afError = error.asAFError?.underlyingError ?? error 
     completion(afError)

asAFError?.underlyingError доступен в среде Alomafire.

Другие вопросы по тегам