ios 主队列上的 performSelectorOnMainThread 和 dispatch_async 有什么区别?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9335434/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 16:54:37  来源:igfitidea点击:

What's the difference between performSelectorOnMainThread and dispatch_async on main queue?

objective-ciosmultithreadinguikitgrand-central-dispatch

提问by Miguel Lomelí

I was having problems modifying a view inside a thread. I tried to add a subview but it took around 6 or more seconds to display. I finally got it working, but I don't know how exactly. So I was wondering why it worked and what's the difference between the following methods:

我在修改线程内的视图时遇到问题。我试图添加一个子视图,但显示大约需要 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];

For reference this were called inside this Completetion Handler of the class of the ACAccountStore.

作为参考,这是在 ACAccountStore 类的这个 Completetion Handler 内部调用的。

accountStore requestAccessToAccountsWithType:accountType withCompletionHandler:^(BOOL granted, NSError *error) {
            if(granted) {
            //my methods were here
            }
}

Edit: When I say it didn't work I meant it took about 6 seconds to display the view I added.

编辑:当我说没有工作我是花了大约6秒才能显示我添加的视图。

回答by Lily Ballard

By default, -performSelectorOnMainThread:withObject:waitUntilDone:only schedules the selector to run in the default run loop mode. If the run loop is in another mode (e.g. the tracking mode), it won't run until the run loop switches back to the default mode. You can get around this with the variant -performSelectorOnMainThread:withObject:waitUntilDone:modes:(by passing all the modes you want it to run in).

默认情况下,-performSelectorOnMainThread:withObject:waitUntilDone:仅调度选择器以默认运行循环模式运行。如果 run loop 处于另一种模式(例如跟踪模式),它不会运行,直到 run loop 切换回默认模式。您可以使用变体来解决这个问题-performSelectorOnMainThread:withObject:waitUntilDone:modes:(通过传递您希望它运行的所有模式)。

On the other hand, dispatch_async(dispatch_get_main_queue(), ^{ ... })will run the block as soon as the main run loop returns control flow back to the event loop. It doesn't care about modes. So if you don't want to care about modes either, dispatch_async()may be the better way to go.

另一方面,dispatch_async(dispatch_get_main_queue(), ^{ ... })一旦主运行循环将控制流返回到事件循环,就会运行该块。它不关心模式。因此,如果您也不想关心模式,那dispatch_async()可能是更好的方法。

回答by Say2Manuj

It's likely because performSelectorOnMainThread:withObject:waitUntilDone:queues the message with common run loop modes. According to Apple's Concurrency Programming Guide, the main queue will interleave queued tasks with other events from the app's run loop. Thus, if there are other events to be processed in the event queue, the queued blocks in the dispatch queue may be run first, even though they were submitted later.

这可能是因为performSelectorOnMainThread:withObject:waitUntilDone:使用常见的运行循环模式将消息排队。根据Apple 的并发编程指南,主队列会将排队的任务与来自应用程序运行循环的其他事件交错。因此,如果事件队列中还有其他事件要处理,则调度队列中排队的块可能会先运行,即使它们是稍后提交的。

This articleis a superb explanation to performSelectorOnMainThreadvs. dispatch_async, which also answers the above question.

这篇文章是对performSelectorOnMainThreadvs.的绝妙解释dispatch_async,也回答了上面的问题。

回答by Ruchira Randana

Did you try thePerformSelectorOnMainThreadwith waitUntilDone=YES

你试试PerformSelectorOnMainThreadwaitUntilDone=YES

Eg:

例如:

Code:

代码:

[viewController performSelectorOnMainThread:@selector(methodThatAddsSubview:) withObject:otherView waitUntilDone:YES];

I think that might solve the issue as of why the PerformSelectorOnMainThreadtakes so long to respond.

我认为这可能会解决为什么PerformSelectorOnMainThread需要这么长时间才能回应的问题。