在AFError中投射服务器响应



我试图实现的是,我有一个NetworkManager,它处理服务器的request,并通过AFError处理错误。然而,有时当服务器响应为4xx时,会有一条带有该响应的自定义消息,我想向用户展示它,但不知道如何实现它

这是我的NetworkManager

static let shared:NetworkManager = {
return NetworkManager()
}()
typealias completionHandler = ((Result<Data, AFError>) ->Void)
func handleAFrequest(request: DataRequest,completion: @escaping completionHandler) {

request.validate(statusCode: 200..<300)
request.responseJSON { (response) in

switch response.result {
case .success(_):

if let data = response.data {
completion(.success(data))
}

case .failure(let error):
print(error.localizedDescription)
switch error {
case .invalidURL(let url):
print("Invalid URL: (url) - (error.localizedDescription)")
completion(.failure(.invalidURL(url: URL)))

case .responseValidationFailed(let reason):
print("Response validation failed: (error.localizedDescription); Reason:(reason)")
completion(.failure(.responseValidationFailed(reason: reason)))

除了错误之外,我希望能够投射服务器响应,并向用户显示响应的Message。StatusCode为4xx:时的服务器响应示例

{
"data":
"code":401;
"Message":"Phone Invalid"
}

我在许多项目中解析了api错误。我相信有一个更好的替代方案来处理用户的显示或错误(如果有的话(。请看我的代码,如果有错误,我会在吐司中显示。在toast中显示不是焦点,但您可以看到我如何处理代码中的错误案例,它从未失败过。请根据您的api调用相应地更改参数

func postMethod(mylist: [String:Any]) {
print(K.APIUrl)
print(K.port)
AF.request("(K.urlFromUrlField!):(K.configPort)/snhttp-01?", method: .put, parameters: mylist)
.authenticate(username: username, password: password)
.response { response in
switch response.result {
case .success:
print("nValidation Successful from put method")
print(response.result)
print(response.value as Any)

//get xml code and error msg if any

if let response = response.data{

let xml = XML.parse(response)
print(xml)
print("nThis is the data sent to the server: (mylist["data"] ?? "No data in data key of the parameter")" )

let code = xml.Response.Code.text ?? "No code value in response"
let responseMessage = xml.Response.Message.text ?? "No message returned from server"

print("nCode value from server: (code)")
print("nResponse message from server: (responseMessage)")
}

else{
print("nSuccess block: Request Successfully sent, BUT there was nothing from the server to unwrap! / nothing sent back from the servernThis is the data sent to the server: (mylist["data"] ?? "No data in data key of the parameter")")
}


case let .failure(error):

if let response = response.data {
let xml = XML.parse(response)

let code = xml.Response.Code.text ?? "nNo code value in response"
let responseMessage = xml.Response.Message.text ?? "No message returned from server"

print("nCode value from server: (code)")
print("nResponse message from server: (responseMessage)")
print(error)

}

else    {
print("nFailure Block: A connection to the server could not be established")

}

}}

}

这段代码从api中解析xml。然而,您可以放弃它,只关注我如何处理响应,从而处理错误。

这是适用于我的解决方案。

你所需要做的就是创建一个自定义的错误类型:

struct APIError: Error, Decodable {
let status: Int?
let message: String?
let key: String?
}

然后调用Alamofire,它将返回一个AFDataResponse,您可以解析它:

func performRequest<T: Decodable>(route: APIRouter, completion: @escaping (APIResponse<T>) -> Void) {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
AF.request(route)
.validate()
.responseDecodable(decoder: decoder, emptyResponseCodes: [200, 201]) { (response: AFDataResponse<T>) in
self.parseResponse(response: response, completion: completion)
}
}

解析是这样完成的:

private func parseResponse<T: Decodable>(response: AFDataResponse<T>, completion: @escaping (APIResponse<T>) -> Void) {
switch response.result {
case .success(let data):
completion(APIResponse<T>.success(data))
case .failure(let error):    
if let data = response.data,
// THIS IS WHERE YOU CAST AFError TO YOUR CUSTOM APIError
let apiError = try? JSONDecoder().decode(APIError.self, from: data) {
completion(APIResponse.failure(apiError))
} else {
completion(APIResponse.failure(error))
}
}
}

希望这能有所帮助!

相关内容

  • 没有找到相关文章

最新更新