【问题标题】:Handle HTTP error with NSURLSession?使用 NSURLSession 处理 HTTP 错误?
【发布时间】:2014-03-05 18:34:06
【问题描述】:

我正在尝试使用 NSURLSession 发送 HTTP 请求。它工作正常,但是当服务器没有响应时,我找不到 HTTP 错误代码的存储位置。 completionHandler的第三个参数只是一个很笼统的NSError。我阅读了NSURLResponse 的参考资料,但一无所获。

NSURLSessionDataTask *dataTask =
    [session dataTaskWithRequest:[self postRequestWithURLString:apiEntry parameters:parameters]
         completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
             if(!error) NSLog([[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);    
         }
    ];
[dataTask resume];

【问题讨论】:

    标签: ios http


    【解决方案1】:

    completionHandler的第二个参数是NSURLResponse,在做HTTP请求的时候,一般是NSHTTPURLResponse。因此,您通常会执行以下操作:

    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:[self postRequestWithURLString:apiEntry parameters:parameters] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    
        // handle basic connectivity issues here
    
        if (error) {
            NSLog(@"dataTaskWithRequest error: %@", error);
            return;
        }
    
        // handle HTTP errors here
    
        if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
    
            NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
    
            if (statusCode != 200) {
                NSLog(@"dataTaskWithRequest HTTP status code: %d", statusCode);
                return;
            }
        }
    
        // otherwise, everything is probably fine and you should interpret the `data` contents
    
        NSLog(@"data: %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    }];
    [dataTask resume];
    

    【讨论】:

    • 将 && response == nil 添加到 if ([response isKindOfClass:[NSHTTPURLResponse class]]) 可能是一个额外的优势
    • 我不这么认为。 if ([response isKindOfClass:[NSHTTPURLResponse class]] && response == nil) 永远不会是真的(responsenil 或者它可能是 HTTP 响应,但绝不会同时出现两者)。也许您的意思是response != nil,但这隐含在对isKindOfClass 的调用中(即,如果responsenil,则在nil 对象上调用isKindOfClass 是不正确的)。如果你真的想要if (response != nil && [response isKindOfClass:[NSHTTPURLResponse class]]),那并没有什么问题,并且使意图明确,但是是多余的。
    • 是的,你是对的。评论中有错别字。我的意思是说“|| response”而不是“&& response”
    • 错误表示超时或没有互联网连接以及任何其他类型的错误将通过 400 或 500 状态码处理是否正确?所以就像你做的那样,你必须提前退出 首先检查错误...然后检查任何非 200 状态代码?
    【解决方案2】:

    斯威夫特 3:

    // handle basic connectivity issues here
    guard error == nil else {
        print("Error: ", error!)
        return
    }
    
    // handle HTTP errors here
    if let httpResponse = response as? HTTPURLResponse {
        let statusCode = httpResponse.statusCode
    
        if (statusCode != 200) {
            print ("dataTaskWithRequest HTTP status code:", statusCode)
            return;
        } 
    }
    
    if let data = data {
        // here, everything is probably fine and you should interpret the `data` contents
    }
    

    【讨论】:

      【解决方案3】:

      你可以试试这样的。我创建了一个简单的方法,它能够将数据发布到服务器并获得服务器响应。您可以通过 NSHTTPURLResponse 类获取服务器状态代码。 希望会有所帮助:)

      -(void) POST:(NSURL *) url URLparameters:(NSString *) parameters success:(void (^)(NSURLSessionDataTask *  task, id   responseObject)) successHandler errorHandler:(void (^)(NSURLSessionDataTask *  task, NSError *  error)) errorHandler{
           requestBody = [[NSMutableURLRequest alloc]
                         initWithURL:url
                         cachePolicy: NSURLRequestUseProtocolCachePolicy
                         timeoutInterval:60.0];
          [requestBody setHTTPMethod:@"POST"];
          [requestBody setValue:@"application/json" forHTTPHeaderField:@"Accept"];
          [requestBody setHTTPBody:[NSData dataWithBytes:
                                    [parameters UTF8String]length:strlen([parameters UTF8String])]];
          NSURLSession *session = [NSURLSession sessionWithConfiguration: sessionConfiguration delegate: self delegateQueue: [NSOperationQueue mainQueue]];
      
          NSURLSessionDataTask *task = [session dataTaskWithRequest:requestBody completionHandler:
                                        ^(NSData *data, NSURLResponse *response, NSError *error) {
                                            NSHTTPURLResponse* respHttp = (NSHTTPURLResponse*) response;
      
                                            if (respHttp.statusCode == SUCCESS) {
                                                NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
                                                successHandler(task, dictionary);
                                                NSLog(@"HTTP_STATUS: success %@", response);
                                            }else if (respHttp.statusCode == UNAUTHORIZE) {
                                                NSLog(@"HTTP_STATUS: anauthorize");
                                            }else if (respHttp.statusCode== BAD_REQUEST) {
                                                NSLog(@"HTTP_STATUS: badrequest");
                                            }else if (respHttp.statusCode == INTERNAL_SERVER_ERROR) {
                                                NSLog(@"HTTP_STATUS: internalerror");
                                            }else if (respHttp.statusCode== NOT_FOUND) {
                                                NSLog(@"HTTP_STATUS: internalerror");
                                            }
                                            errorHandler(task, error);
                                            return;
                                        }];
          [task resume];
      }
      

      【讨论】:

        【解决方案4】:

        如果发生服务器端错误,来自完成处理程序的data 参数可能包含一些有用的信息

        一般来说,我认为您应该在会话委托中实现 URLSession:task:didCompleteWithError: from NSURLSessionTaskDelegate 协议

        文档:NSURLSessionTaskDelegate Protocol Reference

        【讨论】:

          【解决方案5】:

          您可以在allHeaderFields 中拥有整个标题

          let realResponse = response as? NSHTTPURLResponse 
          realResponse.allHeaderFields
          

          请把它转换成objective-C。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-05-21
            • 2021-10-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-09-29
            • 2016-08-06
            • 2016-09-20
            相关资源
            最近更新 更多