Alamofire - 如何从 AFError 获取 API 错误
Posted
技术标签:
【中文标题】Alamofire - 如何从 AFError 获取 API 错误【英文标题】:Alamofire - How to get API error from AFError 【发布时间】:2021-09-22 00:28:10 【问题描述】:在我寻求正确实施 Alamofire 5 并处理自定义错误模型响应的过程中,我还没有找到具有示例的公认答案。
为了尽可能彻底,这是我的 apiclient
class APIClient
static let sessionManager: Session =
let configuration = URLSessionConfiguration.af.default
configuration.timeoutIntervalForRequest = 30
configuration.waitsForConnectivity = true
return Session(configuration: configuration, eventMonitors: [APILogger()])
()
@discardableResult
private static func performRequest<T:Decodable>(route:APIRouter, decoder: JSONDecoder = JSONDecoder(), completion:@escaping (Result<T, AFError>)->Void) -> DataRequest
return sessionManager.request(route)
// .validate(statusCode: 200..<300) // This will kill the server side error response...
.responseDecodable (decoder: decoder) (response: DataResponse<T, AFError>) in
completion(response.result)
static func login(username: String, password: String, completion:@escaping (Result<User, AFError>)->Void)
performRequest(route: APIRouter.login(username: username, password: password), completion: completion)
我就是这样用的
APIClient.login(username: "", password: "") result in
debugPrint(result)
switch result
case .success(let user):
debugPrint("__________SUCCESS__________")
case .failure(let error):
debugPrint("__________FAILURE__________")
debugPrint(error.localizedDescription)
我注意到如果我使用.validate()
调用函数将收到失败但响应数据丢失。环顾四周,注意到 here 和 here 转换为 underlyingError
但那是零。
服务器以我在调用函数级别需要的可解析错误模型进行响应。在 apiclient 级别反序列化 JSON 并将其作为失败返回给调用函数会更愉快。
"errorObject":
"summary": "",
"details": [
...
]
更新
感谢@GIJoeCodes 的评论,我使用路由器实现了这个类似的解决方案。
class APIClient
static let sessionManager: Session =
let configuration = URLSessionConfiguration.af.default
configuration.timeoutIntervalForRequest = 30
configuration.waitsForConnectivity = true
return Session(configuration: configuration, eventMonitors: [APILogger()])
()
@discardableResult
private static func performRequest<T:Decodable>(route:APIRouter, decoder: JSONDecoder = JSONDecoder(), completion:@escaping (_ response: T?, _ error: Error?)->Void)
sessionManager.request(route)
.validate(statusCode: 200..<300) // This will kill the server side error response...
.validate(contentType: ["application/json"])
.responseJSON response in
guard let data = response.data else return
do
switch response.result
case .success:
let object = try decoder.decode(T.self, from: data)
completion(object, nil)
case .failure:
let error = try decoder.decode(ErrorWrapper.self, from: data)
completion(nil, error.error)
catch
debugPrint(error)
// MARK: - Authentication
static func login(username: String, password: String, completion:@escaping (_ response: User?, _ error: Error?)->Void)
performRequest(route: APIRouter.login(username: username, password: password), completion: completion)
这样称呼
APIClient.login(username: "", password: "") (user, error) in
if let error = error
debugPrint("__________FAILURE__________")
debugPrint(error)
return
if let user = user
debugPrint("__________SUCCESS__________")
debugPrint(user)
【问题讨论】:
【参考方案1】:这就是我获取错误和自定义错误消息的方式。在验证中,我得到了 200..
AF.request(
url,
method: .post,
parameters: json,
encoder: JSONParameterEncoder.prettyPrinted,
headers: headers
).validate(statusCode: 200..<300)
.validate(contentType: ["application/json"])
.responseJSON response in
switch response.result
case .success(let result):
let json = JSON(result)
onSuccess()
case .failure(let error):
guard let data = response.data else return
do
let json = try JSON(data: data)
let message = json["message"]
onError(message.rawValue as! String)
catch
print(error)
onError(error.localizedDescription)
debugPrint(response)
【讨论】:
这可能很好用,但是我正在寻找一个包含路由器的解决方案。我对 swift 和 alamofire 很陌生,似乎基于 .responsetype 的闭包很挑剔,即 responseDecodable、responseJSON 等。尝试在上述结构中切换它,我收到“来自抛出函数的无效转换”。使用 xcode 和 swift 一个多星期,我可能不明白这很简单。【参考方案2】:首先,如果您已经拥有Decodable
模型,则无需使用responseJSON
。通过多次解码响应数据,您正在做不必要的工作。使用responseDecodable
并提供您的Decodable
类型,在本例中为您的通用T
。 responseDecodable(of: T)
.
其次,将预期的Decodable
类型包装在枚举中是解决此问题的典型方法。例如:
enum APIResponse<T: Decodable>
case success(T)
case failure(APIError)
然后实现APIResponse
的Decodable
尝试解析成功类型或APIError
(有很多这样的例子)。然后,您可以使用 responseDecodable(of: APIResponse<T>.self)
解析您的回复。
【讨论】:
这是我第一次看到 APIResponse 枚举,我花了几天时间寻找解决方案。请提供指向其使用的完整示例的链接。这将是一个更清洁的解决方案。 我能够找到一个文档,其中包含上述枚举的详细信息。 swiftbysundell.com/articles/the-power-of-result-types-in-swift我不明白您所说的“然后实现 APIResponse 的 Decodable 以尝试解析成功的类型或 APIError”是什么意思。看这个文档,有一个解码块,很明显我不明白该怎么做,因为当按照示例实现时,会有很多错误。以上是关于Alamofire - 如何从 AFError 获取 API 错误的主要内容,如果未能解决你的问题,请参考以下文章
使用消息“Alamofire.AFError.ResponseValidationFailureReason.unacceptableContentType”从存储中获取图像时出错
使用 Flickr API 时出现 Alamofire AFError
Alamofire.AFError.responseValidationFailed
解析 JSON 时出现 AFError Alamofire 5
Alamofire:responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.inputData
值:(failure(Alamofire.AFError.explicitlyCancelled)) 使用 Alamofire 发布者时