views:

15

answers:

0

Hello!

I'm trying to create an endless animation of layer rotating slightly to the left, then slightly to the right and back. So I'm animating 10 degress to the left, then 20 to the right, then 10 to the left again. It works great on simulator, but on device the layer "shivers". It appears like it returns to its previous state every time before it starts next animation. I've read that using

animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;

helps in such cases, but if I use those, the whole layers just freezes in place after first animation and never moves anywhere.

So here's the code:

- (void) initAnimations {
    float baseValue = [[self.layer valueForKey:@"transform.rotation.z"] floatValue];

    rotateLeft = [[CABasicAnimation animationWithKeyPath:@"transform.rotation.z"] retain];
    rotateLeft.fromValue = [NSNumber numberWithFloat:baseValue];
    rotateLeft.toValue = [NSNumber numberWithFloat:baseValue - DegreesToRadians(10.0f)];
    rotateLeft.duration = 0.4f;
    rotateLeft.removedOnCompletion = NO;
    rotateLeft.fillMode = kCAFillModeForwards;
    rotateLeft.repeatCount = 0;
    rotateLeft.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    rotateLeft.delegate = self;

    rotateRight = [[CABasicAnimation animationWithKeyPath:@"transform.rotation.z"] retain];
    rotateRight.fromValue = [NSNumber numberWithFloat:baseValue - DegreesToRadians(10.0f)];
    rotateRight.toValue = [NSNumber numberWithFloat:baseValue + DegreesToRadians(10.0f)];
    rotateRight.duration = 0.6f;
    rotateRight.removedOnCompletion = NO;
    rotateRight.fillMode = kCAFillModeForwards;
    rotateRight.repeatCount = 0;
    rotateRight.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    rotateRight.delegate = self;

    rotateRestore = [[CABasicAnimation animationWithKeyPath:@"transform.rotation.z"] retain];
    rotateRestore.fromValue = [NSNumber numberWithFloat:baseValue + DegreesToRadians(10.0f)];
    rotateRestore.toValue = [NSNumber numberWithFloat:baseValue];
    rotateRestore.duration = 0.3f;
    rotateRestore.removedOnCompletion = NO;
    rotateRestore.fillMode = kCAFillModeForwards;
    rotateRestore.repeatCount = 0;
    rotateRestore.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
    rotateRestore.delegate = self;
}

- (void) beginAnimations {
    if (animationsRunning)
        return;

    [self.layer addAnimation:rotateLeft forKey:nil];
}

- (void)animationDidStart:(CAAnimation *)theAnimation {

}

- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
    [self.layer removeAllAnimations];
    if (self.superview == nil) {
        rotateLeft.delegate = nil;
        rotateRight.delegate = nil;
        rotateRestore.delegate = nil;
        return;
    }

    float dt;
    if (step == 0) {
        dt = 0.7f + (float)(random() % 3) / 10.0f;
    } else {
        dt = 0.4f + (float)(random() % 3) / 10.0f;
    }

    CABasicAnimation* nextAnimation = nil;
    if (step == 0) {
        nextAnimation = rotateRight;
    } else if (step == 1) {
        nextAnimation = rotateRestore;
    } else if (step == 2) {
        nextAnimation = rotateLeft;
    }

    nextAnimation.duration = dt;
    [self.layer addAnimation:nextAnimation forKey:nil];

    step++;
    if (step == 3)
        step = 0;
}

Why isn't it working? I think I've already tried all removedOnCompletion / fillMode combinations and nothing seems to help =(