iphone - 为什么 UIKit 操作必须在主线程上执行?

标签 iphone ios multithreading uikit posix

我想了解为什么不能使用多线程执行 UI 操作。这是否也是其他框架(如 OpenGL 或 cocos2d)的要求?

C# 和 javascript 等其他语言怎么样?我尝试在谷歌中查找,但人们提到了一些我不理解的关于 POSIX 线程的内容。

最佳答案

在 Cocoa Touch 中,UIApplication 即您的应用程序实例附加到主线程,因为该线程是由 UIApplicatioMain() 创建的,它是 cocoa touch 。它设置主事件循环,包括应用程序的运行循环,并开始处理事件。应用程序的主事件循环接收所有 UI 事件,即触摸、手势等。

来自文档 UIApplicationMain() ,

This function instantiates the application object from the principal class and instantiates the delegate (if any) from the given class and sets the delegate for the application. It also sets up the main event loop, including the application’s run loop, and begins processing events. If the application’s Info.plist file specifies a main nib file to be loaded, by including the NSMainNibFile key and a valid nib file name for the value, this function loads that nib file.

这些应用程序 UI 事件进一步转发到 UIResponder 之后的响应链,通常像 UIApplication->UIWindow->UIViewController->UIView->subviews(UIButton等)

响应者处理按钮按下、点击、缩放、滑动等事件,这些事件被转换为 UI 中的变化。因此,正如您所看到的,这些事件链发生在主线程上,这就是为什么 UIKit,包含响应程序的框架应该在主线程上运行。

再次来自文档 UIKit ,

For the most part, UIKit classes should be used only from an application’s main thread. This is particularly true for classes derived from UIResponder or that involve manipulating your application’s user interface in any way.

编辑

为什么 drawRect 需要在主线程上?

drawRect: 作为 UIView 生命周期的一部分由 UIKit 调用。所以 drawRect: 绑定(bind)到主线程。以这种方式绘制是昂贵的,因为它是在主线程上使用 CPU 完成的。硬件加速图形是通过使用 CALayer 技术(核心动画)提供的。

CALayer 另一方面充当 View 的后备存储。然后 View 将只显示其当前状态的缓存位图。对 View 属性的任何更改都将导致 GPU 在备份副本上执行的后备存储发生变化。但是, View 仍然需要提供初始内容并定期更新 View 。我没有真正研究过 OpenGL,但我认为它也使用层(我可能错了)。

我已尝试尽我所知回答这个问题。希望对您有所帮助!

关于iphone - 为什么 UIKit 操作必须在主线程上执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18467114/

相关文章:

ios - Unity3d 命令行自动构建未运行构建后

ios - 没有互联网的icloud同步

iphone - 捕获来自外部(蓝牙)键盘的所有输入

iphone - NSString 到 HEX

android - 确保设备电话号码和应用电话号码相同

c# - 此类线程安全吗?

c++ - omp for with collapse 子句未编译

c - C 中的 POSIX 信号量用于 2 个独立的程序(消费者/生产者)

ios - 访问 ObjC 类中的参数化 swift 方法

iphone - 模拟器中的文档文件夹为空。我的 db.sqlite 在哪里?