在我的应用中,当用户按下按钮时,我启动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];
}];
}
当我尝试在UIAlertView
内创建completionHandler
时会发生类似的行为。
- (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有关,但我不确定。任何有关延迟发生原因的指导将不胜感激。
答案 0 :(得分:9)
主题和您的用户界面
如果您的应用程序具有图形用户界面,建议您从应用程序的主线程接收与用户相关的事件并启动界面更新。 此方法有助于避免与处理用户事件和绘制窗口内容相关的同步问题。某些框架(如Cocoa)通常需要这种行为,但即使对于那些不这样做的框架,将此行为保留在主线程上也具有简化管理用户界面的逻辑的优势。
在主线程上调用UI更新可以解决此问题。通过调用主线程(下面)来围绕您的UI代码。
dispatch_async(dispatch_get_main_queue(), ^{
exampleLabel.text = [NSString stringWithFormat:@"%d", httpResponse.statusCode];
});
还有其他方法可以对主线程进行调用,但使用更简单的GCD命令可以完成这项工作。再次,请参阅Threaded Programming Guide以获取更多信息。
答案 1 :(得分: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];
});
}];
}
答案 2 :(得分:2)
您可以尝试创建一个设置文本的方法,并在您调用的块内:
[self performSelectorOnMainThread:@selector(mySelector) withObject:nil waitUntilDone:NO];
选择器将在主线程上调用并执行。希望这有帮助......