核心动画 - 未调用animationDidStop

时间:2014-10-26 12:12:24

标签: ios iphone core-animation

那里。

在iOS应用中,核心动画回调功能不起作用。

- (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"];
}

但是从未调用过animationDidStop。 如果我像下面那样更改代码,则会调用完成阻止。

- (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];
}

但我不想使用CATransaction。 为什么不调用animationDidStop?

更新 有一种方法可以设置最终值,如

- (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];
}

但最终作业应在动画结束时完成。因为图层有多个动态动画,所以我不知道最终值。

3 个答案:

答案 0 :(得分:6)

我找到了没有调用animationDidStop的原因。

因为动画是在其他线程的循环中添加的,

所以我修好如下。

- (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];
    });
}

答案 1 :(得分:1)

去年我使用的是UIView的动画而不是CABasicAnimation,但是如果我的记忆没有失败,你必须设置endAngle来添加动画,所以试试这个:

- (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:

您在开始动画之前设置anim.toValue = endAngle;,因此动画完成后结束值不会改变。无论如何,您可以在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"];
   }
}

答案 2 :(得分:1)

听起来你不想让动画重置它的位置,这很简单,并且在设置动画时用几行代码实现。

它可以很容易地放在你的代码中:

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

这意味着当你的动画完成时它将保持在最后,任何进一步的动画将来自该状态。