views:

631

answers:

3

I'm aware of the fact that Core Animation dispatches its animations in a seperate thread, as stated in the documentation. Nevertheless, my animations seem to be blocking my main thread. All animations start and finnish. (With or without kCATransactionDisableActions set as true.) but become jumpy and the main runloop stalls.

What am I doing wrong?

Conceptual example:

[NSTimer scheduledTimerWithTimeInterval:0.0333  target:self selector:@selector(gameEngine) userInfo:nil repeats:YES];

- (void)gameEngine 
{    
   [CATransaction begin];
   [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
   myLayer.position = CGPointMake( newX, newY);
   [CATransaction commit];    
}
+1  A: 

Given that you are starting an animation 30 times a second I would imagine you are overwhelming the system. Do the previous animations even have time to start before you issue a new one?

Andrew Grant
They do. They all start and finnish. (With or without kCATransactionDisableActions set as true.) Despite that, Core Animation should not be blocking my main runloop.
Kriem
If CA is overwhelmed your main loop may indeed block. Threads are not magic things with infinite resources.
Andrew Grant
A: 

Well I have the same problem here. I timed my CATransaction block using mach_absolute_time and the times are varying from mostly 0.1 milliseconds to sometimes (approximately 2 out of every 10 frames) 3 or 4 milliseconds. I guess this makes the animation jumpy.

I find this very strange since the animations are always the same kind (a few positions changes), yet the execution duration time varies a lot. It's all the more strange since the animations should run in a seperate thread and not have any influence on the main runloop.

+3  A: 

Creating 30 new animations a second is a really bad idea, and not how Core Animation was intended to be used. Core Animation was designed around the idea that you tell the system where you want your layer (or layer-backed view) to end up, and it figures out the rest, including how many frames to drop to run the animation in the time frame you provide. The animations themselves will run on a background thread, but I believe there's a little setup that needs to be performed first which takes place on the calling thread (usually the main thread). This setup might take longer than 1/30th of a second, which would overload your main thread.

You goal should be to minimize the amount of interaction with Core Animation. If you have a complex, but scripted, motion path (or other property change), set it all up ahead of time using a CAKeyframeAnimation and just call that animation once. If there's something about the motion of your object that needs to be altered in response to user input, only do that when you get the actual input. Changing a property of a CALayer mid-animation will cause it to smoothly move from the middle of its current motion path to its new destination.

If you work with Core Animation in this fashion, you can simultaneously animate up to 50 moving translucent layers at 60 FPS on the iPhone.

Brad Larson