Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

My UIView animation is jerky - how can I optimize the following code?

On the simulator, my animation method runs smoothly. Unfortunately it seems to be very jerky running on an iPhone 4.

I'm not 100% sure of what the best and fastest way to do animations - so any tips on how I can optimize or completely modify my code to speed up this animation would be most appreciated!

Notes:

It's already on the main thread so does that make the 'dispatch_async(dispatch_get_main_queue())' call irrelevant or unhelpful?

Is there a way to pre buffer this animation?

Is there a way to see exactly which part of the code is doing most of the slowing down?

There are only about 3 or 4 views in extensionView.subviews.

I've compiled with -Os.

- (void)extendWithAnimation:(BOOL)animated; {

    isExtended = YES;
    extensionView.hidden = NO;
    topShadowView.hidden = NO;

    topShadowView.frame = CGRectMake(0, defaultHeight, topShadowView.frame.size.width, topShadowView.frame.size.height);
    topShadowView.layer.bounds = CGRectMake(0, 0, topShadowView.frame.size.width, 0);
    extensionView.frame = CGRectMake(0, defaultHeight - 8, DEVICE_WIDTH, extensionHeight + 8);
    extensionView.layer.bounds = CGRectMake(0, 0, DEVICE_WIDTH, 0);

    for (UIView *view in extensionView.subviews) {
        view.transform = CGAffineTransformMakeTranslation(0, -(extensionHeight+8));
    }

    dispatch_async(dispatch_get_main_queue(), ^{

        if (animated) {
            [UIView beginAnimations:nil context:nil];
            [UIView setAnimationDuration:0.3];
            [UIView setAnimationDelegate:self];
        }

        extensionView.layer.bounds = CGRectMake(0, 0, DEVICE_WIDTH, extensionHeight + 8);
        topShadowView.layer.bounds = CGRectMake(0, 0, topShadowView.frame.size.width, extensionHeight + 8);

        for (UIView *view in extensionView.subviews) {
            view.transform = CGAffineTransformIdentity;
        }

        if (animated) {
            [UIView commitAnimations];
        }
    });   
}

Solution:

Solved (thanks Aaron!).

Rendered shadows kill animation big time! Don't use any core graphics shadow properties if you're planning on animating - in my case just a few shadows reduced the frame rate three fold.

like image 530
Jordan Smith Avatar asked Nov 27 '25 17:11

Jordan Smith


2 Answers

  1. Well, if the code is already on the main queue then using dispatch_async is only going to have overhead.
  2. I don't know if this will help (I kind of doubt it), but you might try using [UIView animateWithDuration:.3 animations:{ code... }];
  3. In my past attempts to deal with shadows they've tended to have a pretty big performance hit. You might consider leaving shadows and layers alone and instead create a resizable shadow PNG that you can use in a UIImageView placed behind the the view you want shadowed.
like image 155
Aaron Hayman Avatar answered Nov 30 '25 06:11

Aaron Hayman


Run your code through Instruments (start with Time Profiler). What calls are taking the most time during the animation?

Once you have profiled it, also run it through the Core Animation instrument and enable coloring of off-screen rendering and of non-opaque content. This will help isolate common graphics problems.

I also notice you mention shadows. If you are using the CALayer shadow properties, that's likely killing your performance. But we need more information to really nail this down.

like image 30
Conrad Shultz Avatar answered Nov 30 '25 05:11

Conrad Shultz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!