-4

这就是我正在做的事情:我正在处理一个登录,该登录需要之后操作数据,然后触发一个新视图。我想做一个异步请求,因为服务器并不总是立即响应(我不希望崩溃,因为我用同步连接阻止了主线程)

这就是它现在的样子:

[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *dataReturn, NSData *data, NSError *error)
 {
    //blah blah working code


    //once data is received, it's processed and I want to call a new view
         viewController.hidesBottomBarWhenPushed = YES;
         viewController.name = returnUserData[0];
         viewController.userID = returnUserData[1];
         viewController.role = returnUserData[2];
         viewController.sID = returnUserData[3];
         [self.navigationController pushViewController:viewController animated:YES];
         NSLog(@"Pushed new view controller.");//*/

 }];//end async request

现在我的问题是它实际上并没有在视觉上推动视图。我可以看到我的 NSLog 响应工作正常(新视图立即以“Hello,[name]”响应),但视觉上没有显示任何内容 - 这是一个问题。

不过没关系,我决定改为分离代码并尝试在主线程上运行视图转换

这是我在网上看到的改编:

NSLog(@"init NSURL response");

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSLog(@"Begin async request");
    [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *dataReturn, NSData *data, NSError *error)
     {
         NSLog(@"inside async");
         if (error)
         {
             UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"There was an error communicating with the server.  Please try again." delegate:nil cancelButtonTitle:@"Dismiss" otherButtonTitles:nil];
             [alert show];
             [alert release];
             checkField.text = @"";
         }
         else
         {
             //NSLog(@"raw: %@ - filtered: %@",dataReturn, (NSString *)dataReturn);
             NSDictionary *response = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
             rawJSONData = [response objectForKey:@"d"];
             NSLog(@"Set jsondata");
         }
         NSLog(@"ended async");
     }];//end async request
    NSLog(@"Beginning main thread work");
    dispatch_sync(dispatch_get_main_queue(), ^{
       //not important for the example

所以它正在做的是给我这个:

2014-03-28 21:53:37.059 myApp [652:60b] 初始化 NSURL 响应

2014-03-28 21:53:37.059 myApp [652:3507] 开始异步请求

2014-03-28 21:53:37.059 myApp[652:3507] 开始主线程工作

它完全跳过了嵌入式异步请求。

所以我剩下的是两个脱离主线程的解决方案,它们没有做我想要的: 我想从主线程运行 NSURLConnection,我正在取回我需要解析的 JSON 数据,并且我想等到在转换视图之前获得并解析该数据。

这是我试图做的可能吗?或者我的眼睛是呆滞的,我只是没有看到我应该看到的东西?

4

1 回答 1

0

在您的第一个示例中,您可以通过使用[NSOperationQueue mainQueue]队列而不是我认为是一些后台队列来修复它。或者将您的推送分派到主队列。UI 更新应始终在主队列上完成。

关于您的第二个示例的一些想法:

  1. 您不必将sendAsynchronousRequest请求分派到后台队列,因为它已经异步执行了。将其包装在 adispatch_async中是多余的。

  2. 如果您想在成功解析 JSON 后启动到下一个视图的转换,然后将该代码转换到块的下一个视图completionHandler,就在您解析 JSON 的位置,而不是在sendAsynchronousRequest.

  3. 如果需要,您可以使用您的queue对象,但请确保将您UIAlertView的“转换到视图控制器”代码发送回主队列(因为所有 UI 更新都应在主队列上进行)。mainQueue坦率地说,将 指定为 的队列更容易completionHandler(因为您所拥有的任何东西都不会浪费时间来保证使用后台队列)。

  4. 仅作为惯例,我建议保留NSURLResponse名为 的对象response,并重命名该其他变量。

  5. 您可能希望包含更多错误检查(例如,JSON 是否已成功解析)。有许多服务器错误不会导致要设置的NSError对象completionHandler(例如,这只是基本的互联网连接问题,而不是随机的服务器问题)。

因此,这产生:

NSLog(@"Issuing asynchronous request");
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
 {
     NSLog(@"Received response");
     if (error)
     {
         UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"There was an error communicating with the server.  Please try again." delegate:nil cancelButtonTitle:@"Dismiss" otherButtonTitles:nil];
         [alert show];
         [alert release];
         checkField.text = @"";
     }
     else
     {
         //NSLog(@"raw: %@ - filtered: %@",dataReturn, (NSString *)dataReturn);
         NSError *parseError = nil;
         NSDictionary *responseObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&parseError];
         if (responseObject) 
         {
             rawJSONData = [responseObject objectForKey:@"d"];
             NSLog(@"Set jsondata");

             // initiate the transition to the new view controller here
         }
         else 
         {
             NSLog(@"JSON parse failed: %@", parseError);
             NSLog(@"string from server: %@", [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]);
         }
     }
     NSLog(@"ended async");
 }];//end async request

显然,您应该检查响应和 JSON 解析

于 2014-03-29T04:29:08.483 回答