ios 使用 dispatch_async 或 performSelectorOnMainThread 在主线程上执行 UI 更改?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11530050/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Perform UI Changes on main thread using dispatch_async or performSelectorOnMainThread?
提问by ElasticThoughts
Possible Duplicate:
Grand Central Dispatch (GCD) vs. performSelector - need a better explanation
可能的重复:
Grand Central Dispatch (GCD) 与 performSelector - 需要更好的解释
To execute "stuff" on the main thread, should I use dispatch_async
or performSelectorOnMainThread
? Is there a preferred way, right/or wrong, and/or best practice?
要在主线程上执行“东西”,我应该使用dispatch_async
还是performSelectorOnMainThread
?是否有首选的方式,对/或错,和/或最佳实践?
Example: I'm performing some logic within the block of an NSURLConnection sendAsynchronousRequest:urlRequest
method. Because I'm doing stuff to the main view such as presenting a UIAlertView
I need to show the UIAlertView
on the main thread. To do this I'm using the following code.
示例:我正在NSURLConnection sendAsynchronousRequest:urlRequest
方法块内执行一些逻辑。因为我正在对主视图做一些事情,例如呈现UIAlertView
我需要UIAlertView
在主线程上显示的。为此,我使用以下代码。
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
// code snipped out to keep this question short
if(![NSThread isMainThread])
{
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Oops!" message:@"Some Message" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
});
}
}];
Within that same if(![NSThread isMainThread])
statement I also call some custom methods. The question is, should I use the dispatch_async
method that I'm using above or is it better to use performSelectorOnMainThread
instead? For example, full code below:
在同一个if(![NSThread isMainThread])
语句中,我还调用了一些自定义方法。问题是,我应该dispatch_async
使用上面使用的方法还是performSelectorOnMainThread
改用更好?例如,下面的完整代码:
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
// code snipped out to keep this question short
if(![NSThread isMainThread])
{
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Oops!" message:@"Some Message" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
// call custom methods in dispatch_async?
[self hideLoginSpinner];
});
// or call them here using performSelectorOnMainThread???
[self performSelectorOnMainThread:@selector(hideLoginSpinner) withObject:nil waitUntilDone:NO];
}
}];
FYI - If I DO NOT perform these actions on he main thread I see a few second delay when presenting the UIAlertView
and I receive the following message in the debugger wait_fences: failed to receive reply: 10004003
. I've learned that this is because you need to make changes to the UI on the main thread... In case someone is wondering why I'm doing what I'm doing...
仅供参考 - 如果我不在主线程上执行这些操作UIAlertView
,我会在显示时看到几秒钟的延迟,并且在调试器中收到以下消息wait_fences: failed to receive reply: 10004003
。我了解到这是因为您需要对主线程上的 UI 进行更改...以防有人想知道我为什么要做我正在做的事情...
采纳答案by torrey.lyons
As mentioned in the links provided by Josh Caswell, the two are almost equivalent. The most notable differences is that performSelectorOnMainThread
will only execute in the default run loop mode and will wait if the run loop is running in a tracking or other mode. However, there are some significant differences for writing and maintaining the code.
正如 Josh Caswell 提供的链接中提到的,两者几乎是等价的。最显着的区别是performSelectorOnMainThread
只会在默认的 run loop 模式下执行,如果 run loop 在跟踪或其他模式下运行,它将等待。但是,编写和维护代码存在一些显着差异。
dispatch_async
has the big advantage that the compiler does all its usual tests. If you mistype the method inperformSelectorOnMainThread
you fail at run time, rather than compile time.dispatch_async
makes it much easier to return data from the main thread using the__block
qualifier.dispatch_async
makes it much easier to handle primitive arguments since you don't have to wrap them in an object. However, this comes with a potential pitfall. If you have a pointer to some data remember that block capture does not deep copy the data. On the other hand wrapping the data in an object as you would be forced to do forperformSelectorOnMainThread
does deep copy (unless you set special options). Without a deep copy you can run into intermittent bugs that are frustrating to debug. So this means you should wrap things likechar *
inNSString
before you calldispatch_async
.
dispatch_async
编译器进行所有常规测试的巨大优势。如果您performSelectorOnMainThread
在运行时错误输入方法,而不是编译时失败。dispatch_async
使用__block
限定符从主线程返回数据变得更加容易。dispatch_async
使处理原始参数变得更加容易,因为您不必将它们包装在一个对象中。然而,这有一个潜在的陷阱。如果你有一个指向某个数据记住块捕获不会将数据深层复制。另一方面,将数据包装在一个对象中,因为您将被迫执行performSelectorOnMainThread
深度复制(除非您设置特殊选项)。如果没有深层复制,您可能会遇到令人沮丧的间歇性错误调试。所以这意味着你应该char *
在NSString
调用dispatch_async
.