抱歉,我不确定这里是否使用正确的语言,但是当调用方法因为它们是委托方法,或者因为被列为观察者目标而调用的方法时,它们是否在主要语言上执行线程?
我想知道我是否可以在这些方法中进行UI更改,或者我是否必须将它们包装在
中 dispatch_async(dispatch_get_main_queue(), ^{ UI stuff });
TIA:John
答案 0 :(得分:11)
对于代表来说,这可能会有所不同。如果文档没有指定,那么通常它们会在主线程上发送。传统上UIKit必须在主线程上使用,因此几乎总是从主线程调用这些代理。
对于通知我觉得你想要这个小小的片段。
通知中心同步向观察者发送通知。换句话说,postNotification:方法在所有观察者都收到并处理通知之前不会返回。要异步发送通知,请使用NSNotificationQueue。 在多线程应用程序中,通知始终在发布通知的线程中传递,这可能与观察者注册自己的线程不同。
最后,对于KVO,通知可以来自其他线程。以下是Apple工程师对处理它们的看法。
http://lists.apple.com/archives/cocoa-dev/2007/May/msg00022.html
答案 1 :(得分:8)
如上所述,线程将根据调用者而有所不同。在你的委托方法中,如果你需要适应,你总是可以这样做:
if ([NSThread isMainThread]) {
// do the UI stuff as normal
} else {
dispatch_async(dispatch_get_main_queue(), ^{ UI stuff });
}
答案 2 :(得分:3)
基本思想是,在所有情况下,观察者或委托方法在同一个线程中调用初始通知(对于观察者模式)或委托代码正在运行,因此如果您不确定是否建议分派您的UI阻塞在主线程中。我将在下面的推理中尝试证明这些陈述,当然我可能是错的。
除非在委托协议文档中明确指定,否则在委托模式中,在调用时调用程序正在运行的同一线程中直接调用方法。例如。如果调用者(委托对象)想要调用他的委托并且当前正在“Thread-1”上运行,那么调用将在同一个线程中发生:
// this is running in "Thread-1" --> then aDelegateMethod will continue on "Thread-1"
[myDelegate aDelegateMethod]
就观察者模式而言,我没有看到系统在主线程上显式发送观察通知的任何有效理由,特别是如果发起通知的原始值更改正在另一个线程中运行。实际上在KVO情况下,运行时通过添加一些覆盖setter方法来执行通知的私有方法来更改类定义,并且我没有看到在主线程中显式执行此调用的正当理由。所以根据我的说法,KVO通知可以来自任何线程,这个线程与观察到的类中的值更改相同。
最后,基于NSNotificationCenter的机制看到他的通知由发布原始通知的同一线程调用。 Apple文档中明确说明了这一点(值得一提的是,每个线程都有自己的通知队列)。
因此,在所有情况下都会维护线程,如果您想确保在主队列中调用UI块,请使用您在问题中发布的GCD调用。