There is one problem with your approach: Additional sublayers are added
in draw()
and in animateTimerReset()
and never removed. That can
cause memory problems and slower drawing eventually.
I would suggest to create and add only a single instance of the animation layer, this can for example be done in
override func awakeFromNib() {
layer.addSublayer(animationLayer)
}
Then animate this single animation layer:
func animateTimer(over duration: TimeInterval) {
animationLayer.removeAllAnimations()
let head = CABasicAnimation(keyPath: "strokeEnd")
head.toValue = 1
head.duration = duration
head.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
head.fillMode = kCAFillModeForwards
head.isRemovedOnCompletion = false
animationLayer.add(head, forKey: "strokeEnd")
}
func animateTimerReset() {
let tail = CABasicAnimation(keyPath: "strokeStart")
tail.toValue = 1
tail.duration = 0.1
tail.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
tail.fillMode = kCAFillModeForwards
tail.isRemovedOnCompletion = false
animationLayer.add(tail, forKey: "strokeStart")
}
Some further remarks: At several places the explicit type annotation can be removed, e.g.
var trackColor: UIColor = UIColor(red: 0.3, green: 0.3, blue: 0.3, alpha: 1)
var trackShade: UIColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.6)
var trackLight: UIColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.3)
is shortedshorter written as
var trackColor = UIColor(red: 0.3, green: 0.3, blue: 0.3, alpha: 1)
var trackShade = UIColor(red: 0, green: 0, blue: 0, alpha: 0.6)
var trackLight = UIColor(red: 1, green: 1, blue: 1, alpha: 0.3)
Also the type"implicit member expressions" can be removedused if itthe type is inferred from the context, e e.g.
layer.strokeEnd = CGFloat.leastNormalMagnitude
becomes
layer.strokeEnd = .leastNormalMagnitude
There is one problem with your approach: Additional sublayers are added
in draw()
and in animateTimerReset()
and never removed. That can
cause memory problems and slower drawing eventually.
I would suggest to create and add only a single instance of the animation layer, this can for example be done in
override func awakeFromNib() {
layer.addSublayer(animationLayer)
}
Then animate this single animation layer:
func animateTimer(over duration: TimeInterval) {
animationLayer.removeAllAnimations()
let head = CABasicAnimation(keyPath: "strokeEnd")
head.toValue = 1
head.duration = duration
head.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
head.fillMode = kCAFillModeForwards
head.isRemovedOnCompletion = false
animationLayer.add(head, forKey: "strokeEnd")
}
func animateTimerReset() {
let tail = CABasicAnimation(keyPath: "strokeStart")
tail.toValue = 1
tail.duration = 0.1
tail.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
tail.fillMode = kCAFillModeForwards
tail.isRemovedOnCompletion = false
animationLayer.add(tail, forKey: "strokeStart")
}
Some further remarks: At several places the explicit type annotation can be removed, e.g.
var trackColor: UIColor = UIColor(red: 0.3, green: 0.3, blue: 0.3, alpha: 1)
var trackShade: UIColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.6)
var trackLight: UIColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.3)
is shorted written as
var trackColor = UIColor(red: 0.3, green: 0.3, blue: 0.3, alpha: 1)
var trackShade = UIColor(red: 0, green: 0, blue: 0, alpha: 0.6)
var trackLight = UIColor(red: 1, green: 1, blue: 1, alpha: 0.3)
Also the type can be removed if it is inferred from the context, e.g.
layer.strokeEnd = CGFloat.leastNormalMagnitude
becomes
layer.strokeEnd = .leastNormalMagnitude
There is one problem with your approach: Additional sublayers are added
in draw()
and in animateTimerReset()
and never removed. That can
cause memory problems and slower drawing eventually.
I would suggest to create and add only a single instance of the animation layer, this can for example be done in
override func awakeFromNib() {
layer.addSublayer(animationLayer)
}
Then animate this single animation layer:
func animateTimer(over duration: TimeInterval) {
animationLayer.removeAllAnimations()
let head = CABasicAnimation(keyPath: "strokeEnd")
head.toValue = 1
head.duration = duration
head.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
head.fillMode = kCAFillModeForwards
head.isRemovedOnCompletion = false
animationLayer.add(head, forKey: "strokeEnd")
}
func animateTimerReset() {
let tail = CABasicAnimation(keyPath: "strokeStart")
tail.toValue = 1
tail.duration = 0.1
tail.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
tail.fillMode = kCAFillModeForwards
tail.isRemovedOnCompletion = false
animationLayer.add(tail, forKey: "strokeStart")
}
Some further remarks: At several places the explicit type annotation can be removed, e.g.
var trackColor: UIColor = UIColor(red: 0.3, green: 0.3, blue: 0.3, alpha: 1)
var trackShade: UIColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.6)
var trackLight: UIColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.3)
is shorter written as
var trackColor = UIColor(red: 0.3, green: 0.3, blue: 0.3, alpha: 1)
var trackShade = UIColor(red: 0, green: 0, blue: 0, alpha: 0.6)
var trackLight = UIColor(red: 1, green: 1, blue: 1, alpha: 0.3)
Also "implicit member expressions" can be used if the type is inferred from the context, e.g.
layer.strokeEnd = CGFloat.leastNormalMagnitude
becomes
layer.strokeEnd = .leastNormalMagnitude
There is one problem with your approach: Additional sublayers are added
in draw()
and in animateTimerReset()
and never removed. That can
cause memory problems and slower drawing eventually.
I would suggest to create and add only a single instance of the animation layer, this can for example be done in
override func awakeFromNib() {
layer.addSublayer(animationLayer)
}
Then animate this single animation layer:
func animateTimer(over duration: TimeInterval) {
animationLayer.removeAllAnimations()
let head = CABasicAnimation(keyPath: "strokeEnd")
head.toValue = 1
head.duration = duration
head.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
head.fillMode = kCAFillModeForwards
head.isRemovedOnCompletion = false
animationLayer.add(head, forKey: "strokeEnd")
}
func animateTimerReset() {
let tail = CABasicAnimation(keyPath: "strokeStart")
tail.toValue = 1
tail.duration = 0.1
tail.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
tail.fillMode = kCAFillModeForwards
tail.isRemovedOnCompletion = false
animationLayer.add(tail, forKey: "strokeStart")
}
Some further remarks: At several places the explicit type annotation can be removed, e.g.
var trackColor: UIColor = UIColor(red: 0.3, green: 0.3, blue: 0.3, alpha: 1)
var trackShade: UIColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.6)
var trackLight: UIColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.3)
is shorted written as
var trackColor = UIColor(red: 0.3, green: 0.3, blue: 0.3, alpha: 1)
var trackShade = UIColor(red: 0, green: 0, blue: 0, alpha: 0.6)
var trackLight = UIColor(red: 1, green: 1, blue: 1, alpha: 0.3)
Also the type can be removed if it is inferred from the context, e.g.
layer.strokeEnd = CGFloat.leastNormalMagnitude
becomes
layer.strokeEnd = .leastNormalMagnitude