无法让自定义 activity 指示器进行动画处理

Can't get custom activity indicator to animate

我把一个custom activity indicator that was originally in an Objc file重写成了Swift。 activity 指示器出现在场景中,但没有出现动画。

我需要一些帮助来弄清楚为什么没有出现动画:

vc:

class ViewController: UIViewController {

    fileprivate lazy var customActivityView: CustomActivityView = {
        let customActivityView = CustomActivityView()
        customActivityView.translatesAutoresizingMaskIntoConstraints = false
        customActivityView.delegate = self
        customActivityView.numberOfCircles = 3
        customActivityView.radius = 20
        customActivityView.internalSpacing = 3
        customActivityView.startAnimating()

        return customActivityView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white

        setAnchors()
    }

    fileprivate func setAnchors() {

        view.addSubview(customActivityView)
        customActivityView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        customActivityView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        customActivityView.widthAnchor.constraint(equalToConstant: 100).isActive = true
        customActivityView.heightAnchor.constraint(equalToConstant: 100).isActive = true
    }
}

extension ViewController: CustomActivityViewDelegate {

    func activityIndicatorView(activityIndicatorView: CustomActivityView, circleBackgroundColorAtIndex index: Int) -> UIColor {

        let red = CGFloat(Double((arc4random() % 256)) / 255.0)
        let green = CGFloat(Double((arc4random() % 256)) / 255.0)
        let blue = CGFloat(Double((arc4random() % 256)) / 255.0)
        let alpha: CGFloat = 1
        return UIColor(red: red, green: green, blue: blue, alpha: alpha)
    }
}

Swift 文件:

import UIKit

protocol CustomActivityViewDelegate: class {
    func activityIndicatorView(activityIndicatorView: CustomActivityView, circleBackgroundColorAtIndex index: Int) -> UIColor
}

class CustomActivityView: UIView {

    var numberOfCircles: Int = 0
    var internalSpacing: CGFloat = 0
    var radius: CGFloat = 0
    var delay: CGFloat = 0
    var duration: CFTimeInterval  = 0
    var defaultColor = UIColor.systemPink
    var isAnimating = false

    weak var delegate: CustomActivityViewDelegate?

    override init(frame: CGRect) {
        super.init(frame: frame)

        setupDefaults()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupDefaults()
        fatalError("init(coder:) has not been implemented")
    }

    func setupDefaults() {
        self.translatesAutoresizingMaskIntoConstraints = false
        numberOfCircles = 5
        internalSpacing = 5
        radius = 10
        delay = 0.2
        duration = 0.8
    }

    func createCircleWithRadius(radius: CGFloat, color: UIColor, positionX: CGFloat) -> UIView {
        let circle = UIView(frame: CGRect(x: positionX, y: 0, width: radius * 2, height: radius * 2))
        circle.backgroundColor = color
        circle.layer.cornerRadius = radius
        circle.translatesAutoresizingMaskIntoConstraints = false;
        return circle
    }

    func createAnimationWithDuration(duration: CFTimeInterval, delay: CGFloat) -> CABasicAnimation {
        let anim: CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation")
        anim.fromValue = 0.0
        anim.toValue = 1.0
        anim.autoreverses = true
        anim.duration = duration
        anim.isRemovedOnCompletion = false
        anim.beginTime = CACurrentMediaTime()+Double(delay)
        anim.repeatCount = .infinity
        anim.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
        return anim;
    }

    func addCircles() {

        for i in 0..<numberOfCircles {

            var color: UIColor?

            color = delegate?.activityIndicatorView(activityIndicatorView: self, circleBackgroundColorAtIndex: i)

            let circle = createCircleWithRadius(radius: radius,
                                                color: ((color == nil) ? self.defaultColor : color)!,
                                                positionX: CGFloat(i) * ((2 * self.radius) + self.internalSpacing))

            circle.transform = CGAffineTransform(scaleX: 0.5, y: 0.5)

            circle.layer.add(self.createAnimationWithDuration(duration: self.duration,
                                                              delay: CGFloat(i) * self.delay), forKey: "scale")

            self.addSubview(circle)
        }
    }

    func removeCircles() {
        self.subviews.forEach({ [=12=].removeFromSuperview() })
    }

    @objc func startAnimating() {
        if !isAnimating {
            addCircles()
            self.isHidden = false
            isAnimating = true
        }
    }

    @objc func stopAnimating() {

        if isAnimating {
            removeCircles()
            self.isHidden = true
            isAnimating = false
        }
    }

    func intrinsicContentSize() -> CGSize {
        let width: CGFloat = (CGFloat(self.numberOfCircles) * ((2 * self.radius) + self.internalSpacing)) - self.internalSpacing
        let height: CGFloat = radius * 2
        return CGSize(width: width, height: height)
    }

    func setNumberOfCircles(numberOfCircles: Int) {
        self.numberOfCircles = numberOfCircles
        self.invalidateIntrinsicContentSize()
    }

    func setRadius(radius: CGFloat) {
        self.radius = radius
        self.invalidateIntrinsicContentSize()
    }

    func setInternalSpacing(internalSpacing: CGFloat) {
        self.internalSpacing = internalSpacing
        self.invalidateIntrinsicContentSize()
    }
}

我为动画使用了错误的关键路径:

我用过

// incorrect
let anim: CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation")

但我应该使用

// correct
let anim: CABasicAnimation = CABasicAnimation(keyPath: "transform.scale")