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

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

问题描述:

我在修改线程内的视图时遇到问题。我尝试添加子视图,但显示大约需要6秒或更长时间。我终于搞定了,但我不知道究竟是怎么回事。所以我想知道它为什么有效以及以下方法之间有什么区别:

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:

//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类的处理程序。

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

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

编辑:当我说它不起作用时我意味着显示我添加的视图大约需要6秒钟。

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

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

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).

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

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.