3

在我的应用程序中,当用户按下按钮时,我启动 HTTP 异步请求(使用[NSURLConnection sendAsynchronousRequest...])并更改块UILabel中的文本completionHandler。但是,此更改不会在请求结束时发生,而是在大约 2-3 秒后发生。下面是导致此行为的代码片段。

- (IBAction)requestStuff:(id)sender 
{
    NSURL *url = [NSURL URLWithString:@"http://stackoverflow.com/"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease];

    [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:
     ^(NSURLResponse *response, NSData *data, NSError *error) 
     {
         NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;          
         exampleLabel.text = [NSString stringWithFormat:@"%d", httpResponse.statusCode];
     }];    
}

当我尝试UIAlertViewcompletionHandler.

- (IBAction)requestStuff:(id)sender 
{
    NSURL *url = [NSURL URLWithString:@"http://stackoverflow.com/"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease];

    [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:
     ^(NSURLResponse *response, NSData *data, NSError *error) 
     {
         NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; 

         if ([httpResponse statusCode] == 200) {
             UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"It worked!" 
                                                             message:nil
                                                            delegate:nil 
                                                   cancelButtonTitle:@"OK"
                                                   otherButtonTitles:nil];
             [alert show];
             [alert release];
         }
     }];    
}

但是,一个小的区别[alert show]是执行时屏幕会变暗。警报本身仅在 2-3 秒后出现,就像在前面的场景中一样。

我猜这与应用程序线程如何处理 UI 有关,但我不确定。任何有关延迟发生原因的指导将不胜感激。

4

3 回答 3

9

根据苹果文档

线程和您的用户界面

如果您的应用程序具有图形用户界面,建议您从应用程序的主线程接收与用户相关的事件并启动界面更新。这种方法有助于避免与处理用户事件和绘制窗口内容相关的同步问题。一些框架,例如 Cocoa,通常需要这种行为,但即使对于那些不需要这种行为的框架,将这种行为保留在主线程上具有简化管理用户界面的逻辑的优势。

在主线程上调用你的 UI 更新可以解决这个问题。调用主线程(如下)围绕您的 UI 代码。

dispatch_async(dispatch_get_main_queue(), ^{
   exampleLabel.text = [NSString stringWithFormat:@"%d", httpResponse.statusCode];
});

还有其他方法可以在主线程上进行调用,但使用更简单的 GCD 命令就可以完成这项工作。再次,请参阅线程编程指南了解更多信息。

于 2012-07-08T20:52:31.833 回答
4

这可能会发生,因为所有 UI 内容都应该在主队列中调用。试试这个:

- (IBAction)requestStuff:(id)sender 
{
    NSURL *url = [NSURL URLWithString:@"http://stackoverflow.com/"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease];

    [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:
     ^(NSURLResponse *response, NSData *data, NSError *error) 
     {
         NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;          

         dispatch_async(dispatch_get_main_queue(), ^{
             exampleLabel.text = [NSString stringWithFormat:@"%d", httpResponse.statusCode];
         });
     }];    
}
于 2012-07-08T20:37:05.613 回答
2

您可以尝试创建一个设置文本的方法,并在您调用的块内:

        [self performSelectorOnMainThread:@selector(mySelector) withObject:nil waitUntilDone:NO];

选择器将在主线程上调用和执行。希望这有帮助....

于 2012-07-08T20:47:23.597 回答