Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios performSelectorOnMainThread waitUntilDone:是,与简单调用相比具有优势_Ios_Objective C - Fatal编程技术网

Ios performSelectorOnMainThread waitUntilDone:是,与简单调用相比具有优势

Ios performSelectorOnMainThread waitUntilDone:是,与简单调用相比具有优势,ios,objective-c,Ios,Objective C,你会使用的理由是什么 [self performSelectorOnMainThread:@selector(example:) withObject:nil waitUntilDone:YES]; 在一个更简单的 [self example]; 打电话 看起来他们做的事情是一样的。我所看到的是,在xcode中调试performSelectorOnMainThread似乎比较困难,但在其他方面没有什么区别。如果当前线程是主线程,您是对的,它将执行与直接调用选择器相同的操作 但显然,在主线程上

你会使用的理由是什么

[self performSelectorOnMainThread:@selector(example:) withObject:nil waitUntilDone:YES];
在一个更简单的

[self example];
打电话


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

如果当前线程是主线程,您是对的,它将执行与直接调用选择器相同的操作

但显然,在主线程上没有理由调用
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属性通常只能从主线程访问

这就是为什么要使用
performselectornmainthread:

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 ];
    }
);
编辑

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

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

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

编辑2

顺便说一下,当从不同线程访问属性时,每次需要访问属性时,将它们声明为
原子
显然比使用
performSelectorOnMainThread:
更可取。

也可以考虑<代码> ToxChySyc 或<代码> DexChuxAsYNC ,通过<代码> DeXCHOGGETMIGNEYQueLIG/<代码>作为第一个参数,因为它通常是重新加入主线程的更好方法。

< P>也可以将注释作为回答。
从主线程调用
PerformSelectionMainThread:withObject:waitUntilDone:
,并将
YES
传递到
waitUntilDone:
参数与直接调用选择器相同。换句话说,这是毫无意义的

传递
NO
会产生很大的不同。选择器已排队,稍后将运行

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


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

如果当前线程不是主线程,那么会有很大的区别。我看到很多人在主线程上这样做的例子。他们只是不必要地使用它吗?从主线程调用
performSelectOnMainThread:withObject:waitUntilDone:
,并将
YES
传递到
waitUntilDone:
参数与直接调用选择器相同。换句话说,这是毫无意义的。考虑到原子性,我不同意。拥有一个线程“wait”不会阻止与其他线程(包括主线程)的争用情况。在这种情况下,让一些代码始终在主线程上执行会有所帮助,即使这可能不是最好的使用模式。最大区别的实际情况是事件调度/管理在主运行循环周期中。所以方法直接调用是直接调用主线程,并根据调度运行循环周期执行选择器方法调用,这就是为什么逐行调试很困难的原因。浏览多线程apple文档。当
被传递到
waituntldone:
@rmaddy时,次要注释-使用主线程中的
性能选择器或主线程:
是有意义的(根据正确的需要)。请查看编辑-它可能在原子性方面也有意义。请澄清您的编辑。假设它适用于使用
YES
从主线程调用
PerformSelectionMainThread
,它与直接调用该方法没有什么不同。这实际上是我回答的第一句话。。。或者你是说别的?现在我更糊涂了。你的第一句话陈述了一件事(这与我对答案的第二次评论一致),但你暗示你的第一次编辑意味着其他东西。哪一点?你的最后一点很好,但这不是唯一的原因。您可能有许多线程访问同一个选择器,需要等待。不仅仅是两个。如果选择器没有正确同步,例如使用互斥体,则始终使用主线程在这种情况下会有所帮助。OP从未写过从主线程调用
performselectornmainthread:
。我猜你得再读一遍这个问题:)@Macmade对不起,这是OP在问题下方发布的第一条评论。我正要离开。别担心——那么,在那种情况下,我同意你的回答。但我不认为这是问题的全部。