【问题标题】:IOS Issues with sendAsynchronousRequestsendAsynchronousRequest 的 IOS 问题
【发布时间】:2013-11-06 22:18:08
【问题描述】:

我对@9​​87654321@ 有一些严重的问题。我正在使用休息代理来登录和验证用户。我用来登录的如下所示:

    //Display the progress HUB
    [SVProgressHUD showWithStatus:@"Signing Up..." maskType:SVProgressHUDMaskTypeClear];

    NSError *error;
    [self setUserCredentials];

    //assign the parentView controller to the sender and email to the local class variables
    parentView = sender;
    userEmail = email;

    // create json object for a users session
    NSDictionary* session = [NSDictionary dictionaryWithObjectsAndKeys:
                             email, @"email",
                             password, @"password",
                             [NSDictionary dictionaryWithObjectsAndKeys:
                              [[UIDevice currentDevice] model], @"device",
                              [[UIDevice currentDevice] identifierForVendor].UUIDString, @"device_id",
                              @"APNS", @"push_to",
                              [[NSUserDefaults standardUserDefaults] stringForKey:@"push_id"], @"push_id",
                              nil],
                             @"mession",
                             nil];

    NSData *jsonSession = [NSJSONSerialization dataWithJSONObject:session options:NSJSONWritingPrettyPrinted error:&error];
    NSString *url = [NSString stringWithFormat:@"%@api/v1/messions.json", CoffeeURL];

    NSLog(@"URL: %@", url);

    NSURL *URL = [NSURL URLWithString:url];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL
                                                           cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                       timeoutInterval:30.0];

    [request setHTTPMethod:@"POST"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [request setValue:[NSString stringWithFormat:@"%d", [jsonSession length]] forHTTPHeaderField:@"Content-Length"];
    [request setHTTPBody:jsonSession];

    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {

        NSLog(@"Length: %d", data.length);

        if (error == nil)
        {
            //if no error ocours set the user defualts and create the mession and log into the app
            NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            NSDictionary *JSONResponse = [NSJSONSerialization JSONObjectWithData:[dataString dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error: &error];

            NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;

            NSLog(@"JSON: %@", JSONResponse);
            NSLog(@"Response: %d", httpResponse.statusCode);

            if (JSONResponse != nil && httpResponse.statusCode == 200)
            {
                [self setUserDefualts:password sessionToUse:JSONResponse deckController:viewDeck sender:sender];
            }

            [SVProgressHUD dismiss];
        }
        else
        {
            NSLog(@"Error: %@", error);

            //Dismiss progress HUB here and inform user that an internal error has occured
            [SVProgressHUD dismiss];
            NSString *errorString = @"Sorry, an error has occoured while connecting to the Coffee server.";
            UIAlertView *errorAlertView = [[UIAlertView alloc] initWithTitle:@"Error" message:errorString delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
            [errorAlertView show];
        }
    }];

当我使用有效的用户凭据登录时,此代码可以正常工作。当我使用无效凭据时,服务器会向 iOS 客户端发送一个 401 和一个空 JSON 对象。这应该返回一个 error = nil 和一个状态码 401 以及一个有效的非空响应对象。由于某种原因返回错误并且响应为零:

Error: Error Domain=NSURLErrorDomain Code=-1012 "The operation couldn’t be completed.
(NSURLErrorDomain error -1012.)" UserInfo=0x1cd53b50 
{NSErrorFailingURLKey=http://192.155.94.183/api/v1/messions.json, 
NSErrorFailingURLStringKey=http://192.155.94.183/api/v1/messions.json, 
NSUnderlyingError=0x1cdc2b10 "The operation couldn’t be completed. (kCFErrorDomainCFNetwork
 error -1012.)"}

这让我很难区分发送请求时发生的错误和用户凭据与后端不匹配时服务器生成的 401 错误。当我尝试创建和处理请求时:

NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];

和 NSURLDelegate:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSLog(@"Called Outside!");

    NSDictionary *jsonSession;
    NSUserDefaults *userInfo = [NSUserDefaults standardUserDefaults];
    NSLog(@"Succeeded! Received %d bytes of data", [responseData length]);
    recievedResponse = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];

    NSError *err = nil;
    jsonSession = [NSJSONSerialization JSONObjectWithData:[recievedResponse dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:&err];

    if ([connection.originalRequest.URL isEqual:[NSURL URLWithString:[NSString stringWithFormat:@"%@api/v1/messions.json", CoffeeURL]]])
    {
        NSLog(@"Status: %d", httpResponse.statusCode);
        NSLog(@"JSON: %@", jsonSession);
        NSLog(@"Called Inside!");
    }
}

返回的响应是有效的,当用户输入无效的凭据时,没有抛出错误并且状态码等于 401。为什么这适用于 (void)connectionDidFinishLoading:(NSURLConnection *)connection 而不是 [NSURLConnection sendAsynchronousRequest: queue: completionHandler:]

【问题讨论】:

  • 这与xcode无关。那只是一个编辑器。而是添加了objective-c。编程语言很重要。请解决您的其他问题。
  • 谢谢大家,以后不要再这样了!
  • 恕我直言,如果服务器返回状态码 401,则不应将请求视为失败。因此(根据官方文档)参数 error 必须为 nil,并且参数 data 不得为 nil。另一方面,如果该方法得出请求失败的结论,则参数 data 必须是 nil 并且 error 不能是 nil。但是,这对于状态码 401 来说是完全错误的,服务器可能会随响应一起发送数据,然后客户端无法获取这些数据,因为参数 data 必须是 nil .
  • 既然如此,为什么用户凭证正确时请求会成功?
  • 这是 Apple 尝试将逻辑插入到简单的 HTTP 请求处理中,抽象处理过程中的自然 HTTP 响应的一个示例,这在我看来是 非常 错误的。我完全同意@CouchDeveloper。像这样的废话对于只想要干净简单的 HTTP 并获得明显结果的 REST 开发人员来说是一种负担!

标签: ios objective-c asynchronous nsurlconnection


【解决方案1】:

当 URL 处理系统接收到错误 HTTP 状态代码(即不是2xx)时,不要依赖没有生成错误。

改为使用返回的response,它可以让您访问 HTTP 状态代码(在运行时检查类并强制转换为 NSHTTPURLResponse,以便您可以访问 statusCode)。

【讨论】:

  • 虽然这可能是真的,但这种行为没有意义。当服务器有响应时,一定没有错误。否则,如果有响应和错误,参数data必须为nil,这种情况下响应数据丢失。
  • 您是否尝试过让服务器返回包含一些错误消息的 JSON?
  • 当服务器在 JSON 对象中返回错误时,它仍然返回 nil 响应。
  • 如果您需要比sendAsynchronousRequest 提供的更多灵活性,您将需要使用委托。 sendAsynchronousRequest 很方便,但也有限制。
【解决方案2】:

原来是我们后端服务器的一个错误。有时它会发送非常奇怪的响应代码,iOS NSURLConnection 库处理不当。在这种特殊情况下,它显示为域错误。

【讨论】:

  • 您能否详细说明哪种服务器端更改允许 NSURLConnection 返回正确的 401 响应?
猜你喜欢
  • 1970-01-01
  • 2015-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-04
相关资源
最近更新 更多