2014-03-05 128 views
26

我試圖發送一個HTTP請求NSURLSession。它工作正常,但是當服務器沒有響應時,我找不到HTTP錯誤代碼的存儲位置。 completionHandler的第三個參數只是一個非常通用的NSError。我讀了NSURLResponse的參考資料,但什麼都沒發現。用NSURLSession處理HTTP錯誤?

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]; 

回答

42

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]; 
+0

加入&&響應==零到 如果([響應isKindOfClass:[NSHTTPURLResponse類]])可以是一個額外的好處 – prodeveloper

+1

依吾不。 if([response isKindOfClass:[NSHTTPURLResponse class]] && response == nil)'永遠不會是真的('response'是'nil'或者它可能是HTTP響應,但不會同時出現)。也許你的意思是'response!= nil',但這在'isKindOfClass'調用中是隱含的(即如果'response'爲'nil',則調用'nil'對象上的'isKindOfClass'不是真)。如果你真的想'if(response!= nil && [response isKindOfClass:[NSHTTPURLResponse class]])',那沒有什麼問題,並且明確地表示意圖,但是是多餘的。 – Rob

+1

是的你是對的。評論中有一個錯字。我的意思是提及「|| response」而不是「&& response」 – prodeveloper

1

如果發生服務器端錯誤從完成處理data參數可能包含一些有用的信息

總的來說,我瘦,你應該實現URLSession:task:didCompleteWithError:NSURLSessionTaskDelegate協議會議代表

文檔:NSURLSessionTaskDelegate Protocol Reference

0

你可以擁有整個頭在allHeaderFields

let realResponse = response as? NSHTTPURLResponse 
realResponse.allHeaderFields 

好心將其轉換爲目標-C。

5

斯威夫特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 
} 
1

你可以嘗試這樣的事情。我創建了一個簡單的方法,可以將數據發佈到服務器並獲得服務器響應。您可以通過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]; 
}