我在修改线程内的视图时遇到问题。我试图添加一个子视图,但显示大约需要6秒或更长时间。我终于搞定了,但我不知道究竟是怎么回事。所以我想知道为什么它有效,以下方法之间有什么区别:
//this worked -added the view instantly
dispatch_async(dispatch_get_main_queue(), ^{
//some UI methods ej
[view addSubview: otherView];
}
//this took around 6 or more seconds to display
[viewController performSelectorOnMainThread:@selector(methodThatAddsSubview:) withObject:otherView
waitUntilDone:NO];
//Also didnt work: NSNotification methods - took also around 6 seconds to display
//the observer was in the viewController I wanted to modify
//paired to a method to add a subview.
[[NSNotificationCenter defaultCenter] postNotificationName:
@"notification-identifier" object:object];
作为参考,这是在ACAccountStore类的Completetion Handler中调用的。
accountStore requestAccessToAccountsWithType:accountType withCompletionHandler:^(BOOL granted, NSError *error) {
if(granted) {
//my methods were here
}
}
编辑:当我说它不起作用时,我意味着显示我添加的视图大约需要6秒钟。
答案 0 :(得分:70)
默认情况下,-performSelectorOnMainThread:withObject:waitUntilDone:
仅调度选择器以默认的运行循环模式运行。如果运行循环处于另一种模式(例如跟踪模式),则在运行循环切换回默认模式之前它不会运行。您可以使用变体-performSelectorOnMainThread:withObject:waitUntilDone:modes:
解决此问题(通过传递您希望它运行的所有模式)。
另一方面,只要主运行循环将控制流返回到事件循环,dispatch_async(dispatch_get_main_queue(), ^{ ... })
将运行该块。它不关心模式。因此,如果您不想关心模式,dispatch_async()
可能是更好的方法。
答案 1 :(得分:1)
可能是因为performSelectorOnMainThread:withObject:waitUntilDone:
使用常见的运行循环模式对消息进行排队。根据{{3}},主队列将把排队的任务与应用程序运行循环中的其他事件交错。因此,如果事件队列中还有其他要处理的事件,则可以先运行调度队列中的排队块,即使它们是稍后提交的。
Apple's Concurrency Programming Guide是对performSelectorOnMainThread
与dispatch_async
的绝佳解释,它也回答了上述问题。
答案 2 :(得分:0)
您是否使用PerformSelectorOnMainThread
waitUntilDone=YES
例如:
<强>代码:强>
[viewController performSelectorOnMainThread:@selector(methodThatAddsSubview:) withObject:otherView waitUntilDone:YES];
我认为这可能会解决为什么PerformSelectorOnMainThread
需要这么长时间来回应的问题。