为什么在添加视图后立即启动时 UIView 动画不起作用?

Why is UIView animation not working when starting right after view is added?

UIView 的动画应该在视图添加到父视图后立即开始:

class myView: UIView {
    override func didMoveToSuperview() {
        super.didMoveToSuperview()

        UIView.animate(
            withDuration: duration,
            delay: 0,
            options: .curveLinear,
            animations: {
                CATransaction.begin()
                CATransaction.setAnimationDuration(duration)
                self.layer.colors = [color1, color2]
                CATransaction.commit()
        },
            completion: nil
        )
    }
}

然而,结果是当视图在父视图中可见时动画已经结束。 UIView.animate 没有动画但立即设置 self.layer.colors,可能是因为调用 didMoveToSuperview 时视图尚不可见。

怎样才能让动画正常启动?

可以通过创建 CABasicAnimation 并将其添加到您的 CAGradientLayer 来使用核心动画制作渐变动画。您不需要将其包装在 UIView 动画块中,您可以从 viewDidMoveToSuperview 执行此操作,前提是您在根视图具有后的某个时间将 UIView 子类实例添加到视图层次结构中已添加到 UIWindow。例如,在操场上可以写:

import UIKit
import PlaygroundSupport

class MyView: UIView
{
    var duration = 20.0

    var fromColors = [UIColor.orange.cgColor, UIColor.blue.cgColor]
    var toColors = [UIColor.red.cgColor, UIColor.green.cgColor]

    override func didMoveToSuperview() {
        super.didMoveToSuperview()

        let gradientLayer = CAGradientLayer()
        gradientLayer.frame = bounds
        layer.addSublayer(gradientLayer)

        let animation = CABasicAnimation(keyPath: "colors")
        animation.fromValue = fromColors
        animation.toValue = toColors
        animation.duration = duration
        gradientLayer.add(animation, forKey: nil)

        gradientLayer.colors = toColors
    }
}

class ViewController: UIViewController
{
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        let myView = MyView(frame: view.bounds)
        view.addSubview(myView)
    }
}

PlaygroundPage.current.liveView = ViewController()

并查看从垂直橙色到蓝色渐变到垂直红色到绿色渐变的 20 秒动画。