为什么 所有 UI 操作必须在主线程?— 从框架设计到渲染流程的完整逻辑_ui execution context not found 表明框架在执行ui操作时,当前执行环境
结论先行:UIKit(包含 AppKit 与 SwiftUI 的渲染层 Core Animation)是完全不具备线程安全的框架。事件分发、视图层级变更、布局计算、Core Animation 事务提交与最终合成渲染都绑定到主线程的 RunLoop。任何在其他线程上直接读写视图或
CALayer
的状态,都会破坏这一串行时序,造成数据竞争、渲染状态错乱甚至 Crash。
1. UIApplicationMain 把 主线程 当作 UI 专用通道
main()
调用UIApplicationMain
(或@main
attribute 下 SwiftUI 的App
入口)时,系统会仅为主线程注册 UI 事件源(Mach Port、源 0/1)、Timer、CADisplayLink
等回调。- 其他线程的 RunLoop 没有这些输入源,也就不会收到触摸、键盘、陀螺仪等 UI 事件。
2. RunLoop 的关键阶段与 UI 更新时序
kCFRunLoopBeforeSources
Input Source 0
(如手势识别、按钮点击)