15

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

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

4

5 回答 5

17

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

从文档UIApplicationMain()

此函数从主体类实例化应用程序对象并从给定类实例化委托(如果有)并为应用程序设置委托。它还设置主事件循环,包括应用程序的运行循环,并开始处理事件。如果应用程序的 Info.plist 文件指定要加载的主 nib 文件,通过包含 NSMainNibFile 键和值的有效 nib 文件名,此函数将加载该 nib 文件。

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

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

再次从文档UIKit中,

在大多数情况下,UIKit 类应该只在应用程序的主线程中使用。对于从 UIResponder 派生的类或涉及以任何方式操作应用程序的用户界面的类尤其如此。

编辑

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

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

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

我已尽我所能回答这个问题。希望有帮助!

于 2013-08-27T14:10:02.953 回答
4

来自:https ://www.objc.io/issues/2-concurrency/thread-safe-class-design/

不让 UIKit 成为线程安全的,这是 Apple 方面有意识的设计决定。使其线程安全不会在性能方面为您带来太多好处。它实际上会使许多事情变慢。而 UIKit 与主线程绑定的事实使得编写并发程序和使用 UIKit 变得非常容易。您所要做的就是确保对 UIKit 的调用始终在主线程上进行。

因此,根据这一事实,必须在主线程上访问 UIKit 对象是苹果公司为了提高性能而做出的设计决定。

于 2016-02-03T17:38:55.653 回答
1

C# 的行为相同(请参见此处:保持 UI 线程响应)。UI 更新必须在 UI 线程中完成 - 大多数其他事情应该尽可能在后台完成。

如果不是这种情况,则必须在 UI 中完成的所有更新之间可能会出现同步地狱......

于 2013-08-27T14:56:20.683 回答
0

每个系统,每个库都需要关注线程安全,必须做一些事情来确保线程安全,同时还要注意正确性和性能。

对于 iOS 和 MacOS X 用户界面,我们决定通过只允许在主线程上调用和执行 UI 方法来确保 UI 线程安全。就是这样。

由于发生了许多复杂的事情,至少需要序列化以防止发生完全混乱,因此我认为在后台线程上允许 UI 并没有太多好处。

于 2015-07-27T14:07:10.910 回答
-1

因为您希望用户能够在 UI 更改发生时看到它们。如果您能够在后台线程中执行 UI 更改并在完成时显示它们,那么应用程序的行为似乎不正确。

所有非 UI 操作(或至少是成本非常高的操作,例如下载内容或进行数据库查询)都应在后台线程上进行,而所有 UI 更改必须始终在主线程上进行,以提供与用户一样流畅的操作经验可能。

我不知道 Windows Phone 应用程序在 C# 中的情况,但我希望它是一样的。在Android上,系统甚至不允许你在主线程上下载,让你直接创建一个后台线程。

根据经验 - 当您考虑主线程时,请考虑“用户所看到的”。

于 2013-08-27T14:15:06.410 回答