iOS 委托和观察者调用的方法是在主线程上执行的吗?
抱歉,我不确定这里的语言是否正确,但是当方法被调用时,因为它们要么是委托方法,要么是由于被列为观察者的目标而调用的方法,它们是在主线程上执行的吗?
我想知道我是否可以在这些方法中进行 UI 更改,或者我是否必须将它们包装在
dispatch_async(dispatch_get_main_queue(), ^{ UI stuff });
TIA 中:John
Sorry, I'm not sure of the right language here, but when methods are called because they are either delegate methods, or methods called as a result of being listed as the target of an observer, are they executed on the main thread?
I'm wondering if I can just make UI changes in these methods, or do I have to wrap them in
dispatch_async(dispatch_get_main_queue(), ^{ UI stuff });
TIA: John
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
![扫码二维码加入Web技术交流群](/public/img/jiaqun_03.jpg)
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
对于代表来说,这可能会有所不同。如果文档没有指定,那么通常它们在主线程上发送。传统上 UIKit 必须在主线程上使用,因此这些委托几乎总是从主线程调用。
对于通知,我想你想要这个小片段。
来自 http://developer .apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/nsnotificationcenter_Class/Reference/Reference.html
最后对于 KVO,通知可以来自其他线程。以下是一位苹果工程师对于处理它们的看法。
http://lists.apple.com/archives/cocoa-dev /2007/May/msg00022.html
For delegates this can vary. If the documentation does not specify, then usually they are sent on the main thread. Traditionally UIKit must be used on the main thread so those delegates will almost always be called from the main thread.
For notifications I think you want this little snip.
From http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/nsnotificationcenter_Class/Reference/Reference.html
And finally for KVO, the notifications can come in from other threads. Here is what an Apple Engineer had to say about handling them.
http://lists.apple.com/archives/cocoa-dev/2007/May/msg00022.html
如前所述,线程将根据调用者的不同而有所不同。在你的委托方法中,如果你需要调整,你总是可以这样做:
As stated, the thread will vary based on the caller. In your delegate method, if you need to adapt, you can always do something like this:
基本思想是,在所有情况下,观察者或委托方法都在同一线程中调用,初始通知(对于观察者模式)或委托代码正在运行,因此,如果您不确定,建议在主线程。我将尝试在下面的推理中证明这种说法的合理性,当然我可能是错的。
除非在委托协议文档中明确指定,否则在委托模式中,将在调用者在调用时运行的同一线程中直接调用方法。例如,如果调用者(委托对象)想要调用他的委托并且当前正在“Thread-1”上运行,那么该调用将在同一个线程中发生:
就观察者模式而言,我没有看到任何有效的理由系统在主线程上显式发送观察通知,特别是当发起通知的原始值更改正在另一个线程中运行时。事实上,在 KVO 情况下,运行时通过添加一些重写 setter 方法来执行通知的私有方法来更改类定义,并且我没有看到在主线程中显式执行此调用的有效理由。因此,根据我的说法,KVO 通知可以源自任何线程,并且该线程与在观察到的类中运行值更改的线程相同。
最后,基于 NSNotificationCenter 的机制看到他的通知是由发布原始通知的同一线程调用的。 Apple 文档中明确说明了这一点(值得一提的是,每个线程都有自己的通知队列)。
因此,在所有情况下,线程都会得到维护,如果您想确保在主队列中调用您的 UI 块,请使用您在问题中发布的 GCD 调用。
The basic idea is that in all cases the observer or delegate method are called in the same thread the initial notification (for the observer pattern) or delegating code are running, so if you're not sure it's recommended to dispatch your UI block in the main thread. I will try to justify this statements in the reasoning below, of course I can be wrong.
Unless explicitly specified in the delegate protocol documentation, in the delegate pattern a method is called directly in the same thread the caller is running at the moment of the call. E.g. if the caller (delegating object) wants to call his delegate and is currently running on "Thread-1" then the call will happen in the same thread:
As far as the observer pattern, I don't see any valid reason for the system to send an observing notification explicitly on the main thread, especially if the original value change that originates the notification is running in another thread. In fact in the KVO case the runtime changes the class definition by adding some private methods that override the setter methods to do the notifications, and I don't see a valid reason to do this call explicitly in the main thread. So according to me a KVO notification can originate from any thread and this thread is the same that is running the value change in the observed class.
Finally the NSNotificationCenter based mechanism sees his notifications called by the same thread where the original notification has been posted. This is clearly stated in Apple documentation (and it's worth to say that every thread has its own notification queue).
So in all cases the thread is maintained and if you want to be sure your UI block is called in the main queue then use the GCD call that you posted in your question.