I created a simple application with just a button and an activity indicator. When I press the button I have the activity indicator start animating. In Xcode 4.6 iPhone 6.1 Simulator I see the activity indicator spinning. When I pause the application I sometimes land in libsystem_kernel.dylib`mach_msg_trap. This appears to be on the com.apple.main-thread which is thread 1. Shouldn't pausing the app this way block the main thread and so stop the activity indicator from spinning? It doesn't appear to.
Update: This article ( http://www.dragthing.com/blog/2009/07/how-to-make-your-iphone-app-launch-faster/ ) says "As I discovered, the UIActivityIndicatorView animation is run on a thread by the system – that means, even though my application is blocked inside its initialisation code while it starts up, the spinner will still be spinning." Is it possible the UIActivityIndicatorView is animated off the main thread?
A UIActivityIndicator
draws its image using a UIImageView
subview, and animates the image by attaching a CAKeyframeAnimation
to the image view's layer. You can see the arrangement by printing the view hierarchy:
(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>>
Your app doesn't run these animations. Your app sends these animations to the window server and the window server runs them. That's why they keep running when your app is paused. All threads in your app are paused, but the window server is not paused.
You can prove this by stopping the simulator's window server. It is called backboardd
. From the command line, run this command:
killall -STOP backboardd
You'll see that the activity indicator stops spinning. Then run this command to resume:
killall -CONT backboardd
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With