performSelectorOnMainThread waitUntilDone:优于简单调用的优势

时间:2015-01-17 01:47:48

标签: ios objective-c

您使用

的原因是什么?
[self performSelectorOnMainThread:@selector(example:) withObject:nil waitUntilDone:YES];

更简单

[self example];

呼叫。

似乎他们都做同样的事情。我只看到performSelectorOnMainThread似乎在xcode中调试起来比较困难,但其他方面没有区别。

2 个答案:

答案 0 :(得分:1)

如果当前线程是主线程,那么你是对的,它将直接调用选择器。

但显然,在主线程上没有理由调用performSelectorOnMainThread:(除非你不确定当前线程是否为主线程)。

调用此方法将确保选择器将在主线程上执行,而在另一个线程上执行,这可能因各种原因非常重要。 一个例子是与UI相关的所有内容,因为这些东西通常不应该在辅助线程上完成。

想象一下:

dispatch_async
(
    dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_HIGH, 0 )
    ^( void )
    {
        /* Do heavy work, not blocking the main thread */

        [ myView setBackgroundColor: [ UIColor redColor ] ];
    }
);

以下代码通常被认为是危险的,因为您正在从辅助线程访问UI属性。通常只能从主线程访问UI属性。

这就是您使用performSelectorOnMainThread:

的原因
dispatch_async
(
    dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_HIGH, 0 )
    ^( void )
    {
        /* Do heavy work, not blocking the main thread */

        [ myView performSelectorOnMainThread: @selector( setBackgroundColor: ) withObject: [ UIColor redColor ] waitUntilDone: YES ];
    }
);

修改

您可能会认为,因为您为YES参数传递了waitUntilDone:,所以它应该与直接调用选择器相同。

但不是。问题是被调用的选择器可能没有被同步,以便从不同的线程工作。

考虑设置属性,如上例所示。如果属性为nonatomic,则可能会出现问题,即使您自己的线程“等待”直到执行选择器,因为这不会阻止与其他线程(包括主线程)的竞争条件。

编辑2

顺便说一下,当从不同的线程访问属性时,将它们声明为atomic显然比每次需要访问它时使用performSelectorOnMainThread:更好。 同时考虑dispatch_syncdispatch_async,将dispatch_get_main_queue作为第一个参数传递,因为它通常是重新加入主线程的更好方法。

答案 1 :(得分:1)

也可以将评论作为答案发布。

从主线程调用performSelectOnMainThread:withObject:waitUntilDone:并将YES传递给waitUntilDone:参数与直接调用选择器相同。换句话说,它毫无意义。

传递NO会产生很大的影响。选择器排队等候,稍后会运行。

当然,如果当前线程不是主线程,那么会有很大的不同。

实际上我可以想到在主线程中使用performSelectOnMainThread:withObject:waitUntilDone:YES的一个原因 - 可能从任何线程调用的代码,包括主线程。