I am trying to implement "implicit animations" by overriding CALayer. I've read through the documentation and find it rather complicated. More over, I can't find any decent code examples, or internet posts explaining it well or using any Swift.
I've implemented by subclass BandBaseCG
which attempts to provide implicit animation for property param1
, and overridden needsDisplay(forKey:)
which does get called once with my property where I return true.
But here is where it goes wrong. My understanding is that I must return an object conforming to the CAAction
protocol, say a CABasicAnimation
, and this is what I do. However, action(forKey:)
or defaultAction(forKey:)
do not get called with the param1
key.
So I understand that at some point I can provide Core-Graphics drawing code in draw(in ctx:)
to implement the actual implicit animation in response to some layer.param1 = 2
. But I just cannot get to this point because the API is simply not working how I expected.
Here is my current implementation:
import Foundation
import QuartzCore
class BandBaseCG: CALayer {
@NSManaged var param1: Float
override init(layer: Any) {
super.init(layer: layer)
}
override init() {
super.init()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func action(forKey event: String) -> CAAction? {
print(event)
if event == "param1" {
let ba = CABasicAnimation(keyPath: event)
ba.duration = 2
ba.fromValue = (presentation()! as BandBaseCG).param1
ba.toValue = 2
return ba
}
return super.action(forKey: event)
}
override func draw(in ctx: CGContext) {
print("draw")
}
override class func defaultAction(forKey event: String) -> CAAction? {
if event == "param1" {
let ba = CABasicAnimation(keyPath: event)
ba.duration = 2
ba.fromValue = 0
ba.toValue = 2
return ba
}
return super.defaultAction(forKey: event)
}
override class func needsDisplay(forKey key: String) -> Bool {
print(key)
if key == "param1" {
return true
}
return super.needsDisplay(forKey: key)
}
override func display() {
print("param value: \(param1)")
}
}
Here's a complete working example (from my book):
You will find that if you put a MyView into your app, you can say
and that it will animate the change in the border thickness.