1
votes

Every time I use core animation I get in trouble! Can someone help me with this bug? It has keept me busy for many hours now.

I am animating the bounds and position of a layer. To really change the model layer, and not only the presentation layer, I have learnt that one should set the position and bound to their final toValues before starting the animation.

My code creates a new CALayer-object, and then it animates its position from A to B for the duration of 1s. This works fine!

Later, I use the same code snippet to move the layer back to its original position (A), again for the duration of 1s. This does not work! The layer does move back, but it happens very quickly as the result of the default animation caused by the code lines that assigns the position and bound to their toValues.

I really would like to understand what is wrong with my code! Is it a typo? Or have I misunderstood core animation (again)?

Here is my code. The first method creates a new CALayer object and adds it to the super layer.

-(CALayer*) addLayerFromIm:(UIImage*) im{

    CALayer *lay = [CALayer layer];
    lay.bounds = CGRectMake(0,0, 100,100); // default values never used
    lay.position = CGPointMake(0,0);
    lay.contents = (id) im.CGImage;
    lay.zPosition = 0;
    [self.layer addSublayer:lay];
    return lay;  }

The following method adds the animation to the layer, and it also changes its position- and bounds properties.

-(CALayer*) animateLayer:(CALayer*) lay fromRect:(CGRect)rcFrom toRect:(CGRect)rcTo duration:(float) duration{

    [lay removeAllAnimations];

    lay.position  = rcTo.origin;
    lay.bounds    = CGRectMake( 0,0, rcTo.size.width,rcTo.size.height);

    CABasicAnimation* animP = [CABasicAnimation animationWithKeyPath:@"position"];
    animP.fromValue =[NSValue  valueWithCGPoint:rcFrom.origin];
    animP.toValue =  [NSValue  valueWithCGPoint:rcTo.origin];
    animP.fillMode =  kCAFillModeForwards; 
    animP.duration = duration;
    animP.beginTime = CACurrentMediaTime();
    animP.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    animP.removedOnCompletion = YES;
    [lay addAnimation:animP forKey:nil]; 


    CABasicAnimation* animB = [CABasicAnimation animationWithKeyPath:@"bounds"];
    animB.fromValue = [NSValue valueWithCGRect:CGRectMake(0, 0, rcFrom.size.width, rcFrom.size.height)];
    animB.toValue   = [NSValue valueWithCGRect:CGRectMake(0, 0, rcTo.size.width, rcTo.size.height)];
    animB.fillMode = kCAFillModeForwards;
    animB.duration = duration;
    animB.beginTime = CACurrentMediaTime();
    animB.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    animB.removedOnCompletion = YES;

    [lay addAnimation:animB forKey:nil];

    return lay; }

Here is how the layer is created and animated (this works fine)

UIImage* imDst = [UIImage imageNamed:@"connectionDst.png"]; 

CALayer *lay = [self animateLayer:[self addLayerFromIm:imDst] fromRect:rcA toRect:rcB duration:1.0];

Later on, I try to move back the layer to A.

[self animateLayer:lay fromRect:rcB toRect:rcA duration:1.0];

But then the default animation kicks in and moves the layer in 0.2s. My question is: What is wrong with my code, or my approach?

1

1 Answers

0
votes

I'm gonna say, the approach is a little bit weird. This looks like an auto-reversed animation, which could be simply implemented by the autoreverses property of CABasicAnimation. Or you can try keyframe animation and animateWithDuration: function on UIView.