【问题标题】:cast server response in AFError在 AFError 中投射服务器响应
【发布时间】:2021-09-10 11:04:56
【问题描述】:

我想要实现的是我有一个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"
}

【问题讨论】:

  • 消息中的状态码是“401”,但您的请求是这样吗?您可以检索请求的数据并在失败/成功的情况下对其进行解析。然后您可以将错误/消息嵌入到 AFError 中。查看github.com/Alamofire/Alamofire/blob/master/Source/AFError.swift 哪个更好。
  • @Larme 如何将错误和消息嵌入到 AFError 中?例如completion(.failure(.responseValidationFailed(reason:reason),serverMessage:JSON["data","Message"].string))
  • 创建自己的错误:enum CustomError: Error { case withJSONReason(Dictionary)},然后是let reason = ResponseValidationFailureReason. customValidationFailed(CustomError.withJSONReason(yourDict)) .failure(.responseValidationFailed(reason: reason)?或者类似的东西......
  • @Larme。非常感谢,但我如何访问 reason 内的 message 以将其打印或投射到 UI。
  • case .responseValidationFailed(let reason): switch reason { case .customValidationFailed(let subError}: if let customError = subError as? CustomError { switch customError: case .withJSONReason(let dict): { print(dict} } ;default: break }这就是完整的逻辑,当然你可以分解它。

标签: swift alamofire swift5 alamofire5


【解决方案1】:

我已经在我的许多项目中解析了 api 错误。我相信有更好的选择来处理用户的显示或错误(如果有)。请查看我的代码,如果有错误,我会在祝酒词中显示。在祝酒词中显示不是重点,但您可以看到我如何处理代码中的错误情况并且它从未失败过。请根据您的 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 server\nThis 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。但是,您可以放弃这一点,只关注我如何处理响应以及由此产生的错误。

【讨论】:

  • 你使用的方式是我目前在我的项目中使用的一种很好的方式,但是,由于有很多自定义的 API 调用,我已经实现了handleAFRequest 所以在每个 API 我只创建 request 然后调用它。我希望能够同时回退错误(AFError)和我从服务器收到的消息。
  • @Mohammad 对,我明白了!。但是,在这个项目中,我也在处理许多 API 调用。这段代码来自我创建的一个类,我会在需要的地方从类 obj 访问这个函数。我相信您可以创建一个类并相应地更改 func 参数以提供您想要的功能。 ?
猜你喜欢
  • 2016-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-24
  • 1970-01-01
相关资源
最近更新 更多