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

Mig*_*elí 53 multithreading objective-c uikit grand-central-dispatch ios

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

作为参考,这是在ACAccountStore类的Completetion Handler中调用的.

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

编辑:当我说它不起作用时,我的意思是大约需要6秒才能显示我添加的视图.

Lil*_*ard 70

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

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

  • 这不是真的,它使用默认的运行循环模式.这样记录performSelectorOnMainThread:*"此方法使用****常用运行循环模式将主要线程的运行循环上的消息排队*** - *,即与****NSRunLoopCommonModes**相关联的模式**不变."* (3认同)
  • 什么是模式,什么时候应该关心它们? (2认同)
  • @MattDiPasquale:在iOS上,你基本上可以忽略它们,runloop通常总是在默认模式下运行.在OS X上,您可以看到另外3种模式,"NSConnectionReplyMode","NSModalPanelRunLoopMode"和"NSEventTrackingRunLoopMode".如果您有兴趣,可以查看那些文档. (2认同)
  • 请注意,在iOS中,UITrackingRunLoopMode用于某些触摸事件跟踪(当UIScrollView跟踪触摸移动时). (2认同)