当应用暂停时,为什么活动指示仍然会旋转?

时间:2013-05-04 02:22:02

标签: ios objective-c xcode breakpoints uiactivityindicatorview

我创建了一个简单的应用程序,只有一个按钮和一个活动指示器。当我按下按钮时,我有活动指示器开始动画。在Xcode 4.6 iPhone 6.1 Simulator中,我看到活动指示器正在旋转。当我暂停应用程序时,我有时会登陆libsystem_kernel.dylib`mach_msg_trap。这似乎是在com.apple.main-thread上,它是线程1.不应该以这种方式暂停应用程序阻止主线程,因此阻止活动指示器旋转?它似乎没有。

更新:这篇文章(http://www.dragthing.com/blog/2009/07/how-to-make-your-iphone-app-launch-faster/)说“正如我发现的那样,UIActivityIndi​​catorView动画是由系统在线程上运行的 - 这意味着,即使我的应用程序在启动时被初始化代码阻塞,旋转器仍在旋转。“是否有可能将UIActivityIndi​​catorView设置为主线程的动画?

2 个答案:

答案 0 :(得分:3)

UIActivityIndicator使用UIImageView子视图绘制其图像,并通过将CAKeyframeAnimation附加到图像视图的图层来对图像进行动画处理。您可以通过打印视图层次结构来查看排列:

(lldb) po [[[UIApplication sharedApplication] keyWindow] recursiveDescription]
<UIWindow: 0x7fd778808c00; frame = (0 0; 320 568); autoresize = W+H; gestureRecognizers = <NSArray: 0x6000013b9ef0>; layer = <UIWindowLayer: 0x600001dcd400>>
   | <UIView: 0x7fd778d036f0; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x600001dc5bc0>>
   |    | <UIActivityIndicatorView: 0x7fd778d00280; frame = (177 323; 0 0); opaque = NO; autoresize = RM+BM; tintColor = UIExtendedGrayColorSpace 0 0.45; layer = <CALayer: 0x600001dc5a80>>
   |    |    | <UIImageView: 0x7fd778d06680; frame = (-10 -10; 20 20); opaque = NO;
                 userInteractionEnabled = NO; animations = {
                   contents=<CAKeyframeAnimation: 0x600001dc5f40>;
                   contentsMultiplyColor=<CAKeyframeAnimation: 0x600001dc5fa0>;
                 }; layer = <CALayer: 0x600001dc5ae0>>

您的应用无法运行这些动画。您的应用程序将这些动画发送到窗口服务器,然后窗口服务器运行它们。这就是为什么当您的应用暂停时它们保持运行的原因。您应用中的所有线程均已暂停,但窗口服务器未暂停。

您可以通过停止模拟器的窗口服务器来证明这一点。它称为backboardd。在命令行中,运行以下命令:

killall -STOP backboardd

您将看到活动指示器停止旋转。然后运行以下命令以恢复:

killall -CONT backboardd

答案 1 :(得分:-1)

最近在评论blyabtroi ...

tl; dr:CoreAnimation元素向GPU提供正在进行的渲染指令,CoreGraphics元素不提供,并且需要在运行循环的每次迭代中重新发出指令。

更长的解释: 所有屏幕渲染均通过GPU完成。但是,GPU会根据CPU渲染指令和CPU操纵的图形内存池(这是传统的图形管线)进行渲染。

调试器中的“暂停程序执行”会暂停所有CPU线程,但不会暂停任何GPU进程。任何向GPU发出站立命令的东西(基本上是所有CAAnimation,例如CAKeyframeAnimation)都将指示GPU将其内容渲染到屏幕的该部分,而不停止。通过CPU线程发出命令的任何命令(必须严格执行所有CoreGraphics的内容)都将被暂停。

这可以通过Metal System Trace仪器和下面看到的一个小示例进行说明(在带有文本字段和活动指示器的单视图应用程序的viewDidLoad中运行):

[NSTimer scheduledTimerWithTimeInterval:5.0 repeats:NO block:^(NSTimer * _Nonnull timer) {
    dispatch_async(dispatch_get_main_queue(), ^{
        [NSThread sleepForTimeInterval: 1000000000];
    });
}];

Metal illustration

如您所见,CPU在此期间未报告任何活动-它目前停留在持久的sleepForTimeInterval中。但是,GPU可以不受阻碍地继续运行,并运行其完整的图形管线,并带有CoreAnimation给出的动画命令。