CATransaction setting animation duration not working

10,563

Here's the information you're missing: there are two layer hierarchies in your app. There's the model layer hierarchy, which you normally operate on. Then there's the presentation layer hierarchy, which reflects what's on the screen. Take a look at “Layer Trees Reflect Different Aspects of the Animation State” in the Core Animation Programming Guide for a bit more information, or (highly recommended) watch the Core Animation Essentials video from WWDC 2011.

All of the code you wrote operates on the model layer (as it should).

The system adds implicit animations when it copies a changed animatable property value from a model layer to the corresponding presentation layer.

Only model layers that are in a UIWindow's view hierarchy get presentation layers. The system sends you viewDidLoad before it has added self.view to the window, so there are no presentation layers for self.view or your custom layer yet when viewDidLoad is running.

So one thing you need to do is change the property later, after the view and the layer have been added to the window and the system has created the presentation layers. The viewDidAppear: is late enough.

- (void)viewDidLoad {
    [super viewDidLoad];

    //Modifying base layer
    self.view.layer.backgroundColor = [UIColor orangeColor].CGColor;
    self.view.layer.cornerRadius = 20.0;
    self.view.layer.frame = CGRectInset(self.view.layer.frame, 20, 20);

    // Adding layer
    mylayer = [CALayer layer]; //mylayer declared in .h file
    mylayer.bounds = CGRectMake(0, 0, 100, 100);
    mylayer.position = CGPointMake(100, 100); //In parent coordinate
    mylayer.backgroundColor = [UIColor redColor].CGColor;
    mylayer.contents = (id)[UIImage imageNamed:@"glasses"].CGImage;    
    [self.view.layer addSublayer:mylayer];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    [CATransaction begin]; {
        [CATransaction setAnimationDuration:2];
        mylayer.position=CGPointMake(200.0,200.0);
        mylayer.zPosition=50.0;
        mylayer.opacity=0.5;
    } [CATransaction commit];
}
Share:
10,563
Khaled Barazi
Author by

Khaled Barazi

Started with Casio-PB700 (look it up), then Sinclair ZXSpectrum, Commodore 64/128 and Spectravideo328. Grew up with Basic, Pascal, Assembly and Matlab. Became best friends with C, Obj-C and Swift. Hangs around with Python and friends. iOS apps (Obj-C and Swift) since the first SDK. ML projects. If you feel like it (Bitcoin): 32GGHGm91eDGbgJK2MBVaW7LJWMJyY7GpF

Updated on June 04, 2022

Comments

  • Khaled Barazi
    Khaled Barazi almost 2 years

    I am learning Core Animation and trying out sample examples.

    When I use the following code, the animation duration works

    @implementation ViewController
    
    - (void)viewDidLoad
    {
    [super viewDidLoad];
    
    //Modifying base layer
    self.view.layer.backgroundColor = [UIColor orangeColor].CGColor;
    self.view.layer.cornerRadius = 20.0;
    self.view.layer.frame = CGRectInset(self.view.layer.frame, 20, 20);
    
    //Adding layer
    mylayer=[CALayer layer]; //mylayer declared in .h file
    mylayer.bounds=CGRectMake(0, 0, 100, 100);
    mylayer.position=CGPointMake(100, 100); //In parent coordinate
    mylayer.backgroundColor=[UIColor redColor].CGColor;
    mylayer.contents=(id) [UIImage imageNamed:@"glasses"].CGImage;
    
    [self.view.layer addSublayer:mylayer];
    }
    
    
    - (IBAction)Animate //Simple UIButton
    {
    [CATransaction begin];
    
    // change the animation duration to 2 seconds
    [CATransaction setValue:[NSNumber numberWithFloat:2.0f] forKey:kCATransactionAnimationDuration];
    
    mylayer.position=CGPointMake(200.0,200.0);
    mylayer.zPosition=50.0;
    mylayer.opacity=0.5;
    
    [CATransaction commit];
    }
    @end
    

    On the other hand, if I lumped the Animate method code at the bottom of the ViewDidLoad button so that it happens without pressing any buttons, the animation duration is not respected. I just see the final result without any animation.

    Any thoughts?

    Thanks KMB

  • Khaled Barazi
    Khaled Barazi over 11 years
    Thanks Rob. That worked. I am guessing these brackets around begin to commit are optional.
  • rob mayoff
    rob mayoff over 11 years
    The braces are optional. I like to indent the code between the begin and the commit, and the braces make Xcode automatically indent it.
  • MaxGabriel
    MaxGabriel over 11 years
    I strongly second the referenced WWDC video -- it's an excellent introduction to the many gotchas of CoreAnimation.
  • DuneCat
    DuneCat almost 11 years
    Or, instead of separating it, wrap it in two different CATransactions (in case you need to do it outside initialization).