Core Animation - animationDidStop not called

2019-07-20 07:11发布

there.

in iOS app, Core animation callback don't work.

- (void)startAnim {
    CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    anim.fromValue = startAngle;
    anim.toValue = endAngle;
    anim.duration = 2;
    anim.delegate = self;

    [self.target addAnimation:anim forKey:nil];   // self.target is CALayer instance, it's sublayer of Custom UIView
}

- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
   [self.target setValue:@(endAngle) forKeyPath:@"transform.rotation.z"];
}

But animationDidStop never be called. If I change the code like as following, completion blocked is called.

- (void)startAnim {
    CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    anim.fromValue = startAngle;
    anim.toValue = endAngle;
    anim.duration = 2;
    anim.delegate = self;

    [CATransaction begin];
    [CATransaction setCompletionBlock:^{
        [self.target setValue:@(endAngle) forKeyPath:@"transform.rotation.z"];
    }];

    [self.target addAnimation:anim forKey:nil];
    [CATransaction commit];
}

But I don't want to use CATransaction. Why is not animationDidStop called?

Update: There is a way to set final value like as

- (void)startAnim {
    CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    anim.fromValue = startAngle;
    anim.toValue = endAngle;
    anim.duration = 2;
    anim.delegate = self;

    [self.target setValue:@(endAngle) forKeyPath:@"transform.rotation.z"];
    [self.target addAnimation:anim forKey:nil];
}

But final assignment should be done when the animation is finished. Because there are multiple dynamic animations of layer, so I don't know final value.

3条回答
萌系小妹纸
2楼-- · 2019-07-20 07:47

I found the reason why animationDidStop is not called.

Because animation was added in loop of other thread,

So I fixed like as following.

- (void)startAnim {
    dispatch_async(dispatch_get_main_queue(), ^{
        CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
        anim.fromValue = startAngle;
        anim.toValue = endAngle;
        anim.duration = 2;
        anim.delegate = self;

        [self.target addAnimation:anim forKey:nil];
    });
}
查看更多
可以哭但决不认输i
3楼-- · 2019-07-20 07:48

Last year I use animation of UIView instead CABasicAnimation, but if my memory does not fail you have to set endAngle befor add animation, so try this:

- (void)startAnim {
    CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    anim.fromValue = startAngle;
    anim.toValue = endAngle;
    anim.duration = 2;
    anim.delegate = self;

    [self.target setValue:@(endAngle) forKeyPath:@"transform.rotation.z"];
    [self.target addAnimation:anim forKey:nil];
}

UPD:

You are setting anim.toValue = endAngle; before start animation, so its not good that end value changes after animation complete. Anyway you can set it again in animationDidStop

- (void)startAnim {
    CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    anim.fromValue = startAngle;
    anim.toValue = endAngle;
    anim.duration = 2;
    anim.delegate = self;

    intermediateAngle = endAngle;

    [self.target setValue:@(endAngle) forKeyPath:@"transform.rotation.z"];
    [self.target addAnimation:anim forKey:nil];
}

- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
   if (intermediateAngle != endAngle) {
      startAngle = intermediateAngle;
      [self startAnim]; // or just [self.target setValue:@(endAngle) forKeyPath:@"transform.rotation.z"];
   }
}
查看更多
再贱就再见
4楼-- · 2019-07-20 08:00

To me it sounds like you dont want the animation to reset its position, this is quite simple and achieved with a couple lines of code when setting up the animation.

It can be easily placed in your code like such:

anim.fillMode = kCAFillModeForwards; anim.removedOnCompletion = NO;

What this means is when your animation has finished it will remain at the end and any further animations will be from that state.

查看更多
登录 后发表回答