CABasicAnimation 执行不可靠
Posted
技术标签:
【中文标题】CABasicAnimation 执行不可靠【英文标题】:Unreliable execution from CABasicAnimation 【发布时间】:2014-08-29 21:34:02 【问题描述】:我正在尝试在 CALayer 上实现自定义属性的动画。我已经将该属性设置为动态的,并且它主要工作。在我的应用程序中,我可能有十几个或更多该层的实例,所有这些实例都应该同时进行动画处理。但是,有时当动画被触发时,一些图层不执行动画。他们简单地直接跳转到最终值。
在尝试调试问题时,看起来当动画开始时,出现问题的图层会在其模型图层上重新绘制动画属性的最终值。其余层仅使用动画属性的瞬态值在其表示层上重绘。通常是最后一层有问题,但有时是随机层。
它是如此零星,我不确定下一步该往哪里看。
这里是触发动画的sn-p代码:
@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];
【问题讨论】:
您对动画的要求如何?根据我的经验,使用键值编码总是有效的。所以如果你说例如myLayer.aspectModeFraction = whatever
,试着改用 [myLayer setValue:whatever forKey:@"aspectModeFraction"]
看看是否有区别。
【参考方案1】:
看起来您拥有大部分零件。自定义属性动画中有很多小部分,this talk 可能仍然有帮助,看起来您可能已经完成了主要工作。
我首先怀疑调用代码。我会确保你没有抑制动画,或者修改主线程之外的任何 UIKit 片段。
值得注意的是,使用@dynamic
复制图层属性的技巧可能不受官方支持。 (这是“似乎有效”的事情之一,而不是来自我认识的任何文档;当我与一些 Apple 工程师谈论它时,他们从未听说过这样做。)如果你仅在 10.9+ 上遇到问题,您可以尝试将您对 @dynamic
的使用替换为您在 initWithLayer:
中复制的标准属性。
【讨论】:
动画自定义属性是官方的;有 Apple sample code 专门展示了如何做到这一点。事实上,整个动画系统都是专门设计成可以通过这种方式进行扩展的。 我知道您可以为自定义属性设置动画。事实上,我所说的@动态属性自动复制没有记录在案,并且可能没有得到真正的支持。如果您查看链接的代码,它们会在initWithLayer:
中实现复制,以及使用@dynamic。 (参见 CustomAnimatableProperty/BulbLayer.m)您没有表明您有一个 initWithLayer:
方法来处理这个问题。【参考方案2】:
感谢您的建议。我最终找到了问题所在。我已经优化了绘图代码,只在这个参数改变时才做一些计算。当参数更新时,我将计算标记为脏,以便在下一个绘制循环期间重新计算它们。脏标志是通过参数上的自定义设置器设置的。当我切换到@dynamic(这似乎是 CAAnimations 所必需的?)时,自定义设置器必须消失,所以我通过让对象自己执行 KVO 来更新脏标志。事实证明,observeValueForKeyPath:... 在动画期间没有被调用。它对最终值进行了一次更新,但没有中间值。
无论如何,每次都放弃优化并进行完整计算可以解决问题。 KVO 在动画值上没有按预期工作似乎是罪魁祸首。
【讨论】:
以上是关于CABasicAnimation 执行不可靠的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 CABasicAnimation 从一个点移动到另一个点?
在 CABasicAnimation 期间 UIButton 未显示选定状态