来自CABasicAnimation的不可靠执行

时间:2014-08-29 21:34:03

标签: cocoa calayer caanimation

我试图在CALayer上实现自定义属性的动画。我已将该物业设置为动态,并且它主要起作用。在我的应用程序中,我可能有十几个或更多这个图层的实例,所有这些实例都应该同时生成动画。但是,有时当触发动画时,一些图层不会执行动画。他们简单地直接跳到最终值。

在尝试调试问题时,看起来当动画开始时,带有问题的图层会在其模型图层上重新绘制动画属性的最终值。其余图层仅使用动画属性的瞬态值在其表示层上重绘。它通常是有问题的最后一层,但有时它是随机层。

这是零星的,我不确定下一步该往下看。

这是触发动画的代码片段:

@dynamic aspectModeFraction;

- (id<CAAction>)actionForKey:(NSString *)key
{
    if ([key isEqualToString:@"aspectModeFraction"])
    {
        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:key];
        animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
        animation.fromValue = @([[self presentationLayer] aspectModeFraction]);
        animation.duration = 2.0f;
        animation.delegate = self;
        return animation;
    }
    return [super actionForKey:key];
}

+ (BOOL)needsDisplayForKey:(NSString *)key {

    if ([@"fullRect"           isEqualToString:key]) { return YES; }
    if ([@"localRect"          isEqualToString:key]) { return YES; }
    if ([@"screens"            isEqualToString:key]) { return YES; }
    if ([@"aspectModeFraction" isEqualToString:key]) { return YES; }

    return [super needsDisplayForKey:key];
}

2 个答案:

答案 0 :(得分:0)

看起来你有大部分的部分。自定义属性动画中有很多小部件,this talk可能仍然有用,看起来你可能已经掌握了重要的东西。

我首先怀疑调用代码。我确保你没有压制动画,或者修改主线程中的任何UIKit碎片。

值得注意的是,使用@dynamic来复制图层属性的技巧可能无法正式支持。 (这似乎是“似乎有效”的事情之一,而不是出自我所知道的任何文件;当我与一些苹果工程师谈过这件事时,他们从来没有听说过那样做。)如果你'只有10.9+才能看到问题,您可以尝试将@dynamic的使用替换为您在initWithLayer:中复制的标准属性。

答案 1 :(得分:0)

感谢您的建议。我最终追查了这个问题。我已经优化了绘图代码,只在这个参数改变时做了一些计算。当参数更新时,我将计算标记为脏,因此在下一个绘制循环期间将重新计算它们。脏标志是通过参数上的自定义设置器设置的。当我切换到@dynamic(这似乎是CAAnimations需要?)时,自定义setter必须消失,所以我通过让对象自己做KVO来更新脏标志。事实证明,observeValueForKeyPath:...在动画期间没有被调用。它有一个最终值的更新,但没有中间体。

无论如何,每次解决问题时都放弃优化并进行完整计算。 KVO对动画价值没有按预期工作似乎是罪魁祸首。