How to use Swift 4 KeyPath in CAShapeLayer animati

2020-07-08 03:47发布

问题:

If I write Swift 3 code it would look like this:

let animation = CABasicAnimation(keyPath: #keyPath(CAShapeLayer.path))

But I tried to use Swift 4 new syntax for keyPath and I got:

let keyPath = \CAShapeLayer.path
let animation = CABasicAnimation(keyPath: keyPath) // error line

> Error: Cannot convert value of type 'ReferenceWritableKeyPath' to expected argument type 'String?'

How can I use key path in this situation with swift 4?

回答1:

As for now CABasicAnimation still uses the old String keyPaths so you should still use #keyPath(CAShapeLayer.path) even though you are using Swift 4.

Apple will probably update all it's APIs in the future to make use of these safer key path references. But for now you are stuck with "unsafe" Strings.



回答2:

Yes, it is possible to use swift keypaths. Like:

extension UIView {

func animateLayer<Value>(_ keyPath: WritableKeyPath<CALayer, Value>, to value:Value, duration: CFTimeInterval) {

    let keyString = NSExpression(forKeyPath: keyPath).keyPath
    let animation = CABasicAnimation(keyPath: keyString)
    animation.fromValue = self.layer[keyPath: keyPath]
    animation.toValue = value
    animation.duration = duration
    self.layer.add(animation, forKey: animation.keyPath)
    var thelayer = layer
    thelayer[keyPath: keyPath] = value
}
}

Usage like:

animateLayer(\.shadowOffset, to: CGSize(width: 3, height: 3), duration:1)
animateLayer(\.shadowOpacity, to: 0.4, duration: 1)

It's not thoroughly tested. but worked for me.



回答3:

For Swift 5 you can use something similar to this:

let ba: CABasicAnimation = CABasicAnimation(keyPath: #keyPath(CAEmitterLayer.emitterPosition))
ba.fromValue = topMid
ba.toValue = topMid.offsetBy(dx: dx, dy: dy)
ba.duration = 6
ba.autoreverses = true
ba.repeatCount = .infinity
snowflakeEmitterLayer.add(ba, forKey: nil)


标签: ios swift swift4