欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

CAAnimation的一些坑记录

程序员文章站 2024-03-26 10:09:59
...

关于CAAnimation结束后的隐式还原动画

我们经常用以下两行代码来设置animation结束后的状态保持结束时的效果不动

  animation.isRemovedOnCompletion = false
  animation.fillMode = kCAFillModeForwards 

通过这两行代码,我们可以让动画在执行结束之后保持结束那一帧的状态不动。
但是 →→→
比如我们实现了一个位移动画,如果我们打印view或者单独的layer的frame我们可以发现,动画对象的frame还和动画开始之前的值一样,并未改变????
这是因为视图在动画中改变的只是 presentation树, 这个树的作用就是展示layer的各种效果;而与之对应的还有一个 model树, 这个树才是保存了视图真实状态的,在动画过程中以及动画结束后,如果没有直接对视图的frame进行设置,model树中的状态是不会变化的。

因此,用上面两行代码来保持动画结束后的状态算不上是一个聪明的办法,除非你真的需要保持初始状态不变……
接下来,我们可以注释掉上面的两行代码,并在构造动画的时候给动画保存一个终止状态的属性记录,我们可以使用NSObject的 setValue:forKey:函数来实现这一点

  let animation = CABasicAnimation(keyPath: "position")
  // ...
  animation.setValue(endPosition, forKey: "AniEndPosition")

之后再在动画结束的代理方法中将状态赋值给视图——

  func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
        if flag {
             // 文中未显示的前置代码中对不同的动画进行了identifier的设置,
             // 这里直接用于判断是哪个动画进入了代理方法,这是个好习惯,当然最好用常量代替字符串直接书写,防止typo错误的发生????
            if anim.value(forKey: "AnimationIdentifier") as! String == "moveToAnimation" {
                CATransaction.begin()
                CATransaction.setDisableActions(true)
                aniLayer.position = anim.value(forKey: "positionToEnd") as! CGPoint
                CATransaction.commit()
            }
        }
    }

上面的代码中还有一对CATransaction,这个是CAAnimation在执行过程中自动添加并在每一帧开始和结束时自动begin和commit的,同时也是CAAnimation结束后隐式动画问题的来源。如果不加这段代码,最后修改frame之前的一帧,我们会看到视图闪铄回initial位置一下再跳到最终frame,这必然是我们不愿意看到的????
至此,我们就完成了动画结束后保持最新状态的操作。

layer.add(anim:forKey:)的调用时间

这个坑其实并不难跳出来,但是很多时候真的是一时疏忽就容易坑到自己……????
还是上面的 animationDidStop(_ anim: finished:) 中的例子,最开始我写这个的时候,每次到if anim.value(forKey: "AnimationIdentifier") as! String == "moveToAnimation",程序都会crash掉……然后发现这个表达式取出来的是个nil……
所以,问题很明显了——我并没有成功地执行animation.setValue("moveToAnimation", forKey: "AnimationIdentifier")……
review一下代码,发现问题了……这一行我写在了layer.add(anim:forKey:)的后面……
addAnimation的方法其实是copy了一个animation对象给layer。所以,一切对animation的设置,一定要放在 layer.add(anim: forKey:) 之前进行,否则是不会生效的!!!