【问题标题】:How to get status code in AFNetworking如何在 AFNetworking 中获取状态码
【发布时间】:2014-01-01 04:53:17
【问题描述】:

我有一个方法,用于授权用户。我需要基本授权。

    NSString *url = [NSString stringWithFormat:@"%@/rest/api/person/auth", host];
    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    [manager setRequestSerializer:[AFHTTPRequestSerializer serializer]];
    [manager.requestSerializer setAuthorizationHeaderFieldWithUsername:_loginField.text password:_passwordField.text];
    [manager setResponseSerializer:[AFJSONResponseSerializer serializer]];
    [manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        [self parseResponseForUser:responseObject];
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Error %@ ",error);
    }];

这里的主要问题是确定错误类型。我可能有授权错误和网络连接问题错误(主机不可访问)。 当登录名和密码不符合条件时,失败块运行。例如,如果我输入错误的密码并登录,我会收到此错误消息。:

Error Domain=NSCocoaErrorDomain Code=3840 "无法执行该操作 完全的。 (Cocoa 错误 3840。)”(JSON 文本不是以数组开头或 允许未设置片段的对象和选项。)

我应该如何捕捉错误类型?

【问题讨论】:

  • 您能发布您想要获取的 JSON 吗?
  • 我已经更新了我的问题,我已经发布了我想要得到的回复

标签: ios afnetworking afnetworking-2


【解决方案1】:

终于找到答案了,可能对某人有帮助。我只需要使用:

NSInteger statusCode = operation.response.statusCode;

我可以像这样抓住它:

    [manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSLog(@"response:%@", responseObject);
        [self parseResponseForUser:responseObject];
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSInteger statusCode = operation.response.statusCode;
        if(statusCode == 401) {
        } else if (statusCode == 404) {
        }
    }];

【讨论】:

  • NSInteger 应该在我们转向 64 位架构时继续使用。
  • 这对于使用任务的AFURLSessionManager 无效,而不是AFHTTPRequestOperation
【解决方案2】:

在 AFNetworking 3.0+ 和发生错误的情况下,您可以访问失败块的 error.userInfo 对象中的状态代码:

failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

    NSHTTPURLResponse *response = error.userInfo[AFNetworkingOperationFailingURLResponseErrorKey];

    NSInteger statusCode = response.statusCode;

    // Do something with the status code
}];

【讨论】:

    【解决方案3】:

    您可以尝试从错误中获取代码,然后相应地显示消息。

    failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSInteger statusCode = error.code;
        if(statusCode == -1001) {
          // request timed out
        } else if (statusCode == -1009 || statusCode || -1004) {
          // no internet connectivity
        }
    }];
    

    同样,您可以检查其他代码。

    【讨论】:

      【解决方案4】:

      我是这样做的。

      [self.httpClient GET:@"someAPI"
                parameters:parametersDictionary
                   success:^(NSURLSessionDataTask *task, id responseObject) {
                   } failure:^(NSURLSessionDataTask *task, NSError *error) {
                     NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
                     NSInteger statusCode = [response statusCode];
                     switch (statusCode) {
                       case 404:
                         break;
                       default:
                         break;
                     }
                   }];
      

      【讨论】:

        【解决方案5】:

        使用 NSURLError 枚举改进了 alok srivastava 的响应:

        failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSInteger statusCode = error.code;
        if(statusCode == NSURLErrorTimedOut) {
          // request timed out
        } else if (statusCode == NSURLErrorNotConnectedToInternet || statusCode || NSURLErrorCannotConnectToHost) {
          // no internet connectivity
        }}];
        

        【讨论】:

          【解决方案6】:

          这里是如何在 Swift 中做到这一点

          ((NSURLSessionDataTask, NSError) -> Void) = { (sessionDataTask :NSURLSessionDataTask, responseError : NSError) -> Void in
              let response  = sessionDataTask.response as! NSHTTPURLResponse
              switch (statusCode) {
                case 404:
                  // do stuff
                case 401:
                  // do stuff
                default:
                  break;
              }
          }
          

          【讨论】:

            【解决方案7】:

            看起来您的服务器可能会使用 HTML 进行响应,也可能会使用 JSON 进行响应。但是当你输入时:

            [manager setResponseSerializer:[AFJSONResponseSerializer serializer]];
            

            你告诉 AFNetworking 期待 JSON。

            如果不是 JSON,请尝试告诉它处理常规 HTTP 响应:

            NSArray *serializers = @[[AFJSONResponseSerializer serializer], [AFHTTPResponseSerializer serializer]];
            AFCompoundSerializer *compoundResponseSerializer = [AFCompoundSerializer compoundSerializerWithResponseSerializers:serializers];
            [manager setResponseSerializer:compoundResponseSerializer];
            

            现在,如果 JSON 序列化程序失败,请求将被传递到 AFHTTPResponseSerializer,它应该使用适当的 HTTP 错误代码而不是 JSON 解析错误来调用您的失败块。

            顺便说一句,AFHTTPResponseSerializer 是可子类化的,因此如果您想要更具体的行为,请随意查看该选项。

            【讨论】:

            • 谢谢,亚伦。今天我尝试了这个解决方案,但我被卡住了,我应该从哪里导入 AFCompoundSerializer。阅读 AFNetworking 的文档,我找到了获取 statusCode 的方法。
            【解决方案8】:

            这种情况经常发生,如果服务器发送错误,服务器可能会以不同于请求的内容类型发送响应。

            例如,当使用 JSON 作为 Content-Type 发送请求并期望来自服务器的 JSON 响应时,可以指定以下请求标头:

            Content-Type: application/json
            Accept: application/json
            

            当请求因身份验证错误而失败时,服务器可能会向您发送状态代码401 (Unauthorized) 以及包含相关诊断信息的可选响应。

            严格来说,Web 服务器应该尊重 Accept 标头,但不幸的是,有些服务器不会并且会在 text/html 中发送“标准”错误响应。不过,详细信息应在 API 中指定。

            您的实现应该优雅地处理这种情况。也就是说,您的响应处理程序必须根据响应的Content-Type 编码(或解析)响应数据,例如text/html 或在合适的情况下忽略它。更准确地说,您应该始终查询 HTTP 状态代码和内容类型,然后做出明智的决定,您希望如何处理响应。

            查看 Aron Brager 的回答如何使用 AFN 解决该问题。

            【讨论】:

              【解决方案9】:

              您的 Json 必须是:

              {
                  "access" : "1",
                  "admin" : "0",
                  "code" : "constantine2",
              
                  ...
              
                  "positions" : [
                              {
                          "departmentID" : "992c93ee-2fa7-4e53-be5f-4e32a45ba5e6",
                          "departmentName" : "Dev-C++ resources page (libraries, sources, updates...)",
                          ....
                      }
                  ],
                  "userid" : "3b660c13-b856-41fa-a386-814a7b43bacc"
              }
              

              【讨论】:

              • 我确信 JSON 是正确的,因为当我输入正确的登录名和密码时,我可以解析数据。当我输入错误的登录名或密码时会出现此问题。服务器端向我发送 html 响应(错误 401,用户未授权)而不是 json。我想捕捉错误,所以如果错误类型等于 401,我想显示一个警报视图,如“用户未授权”,如果错误类型等于 404,我想显示用户“不正确的 url 消息”。任何帮助将不胜感激。
              • 正确地写下你的问题而不是 -1。答案是:第一个 [self parseResponseForUser:responseObject];检查您的 responseObject 内容和类型,以及 if(is 404 ?) {alert} else {[self parseResponseForUser:responseObject];}
              • 我没有把-1给你。我只有13个声望,我什至不能投票。我现在只能选择最佳答案
              • 我很抱歉。别人——非常聪明
              猜你喜欢
              • 2013-10-06
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-05-05
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多