user3069232 user3069232 - 1 month ago 23
Swift Question

CAShapeLayer animation doesn't fire animationDidStop

Running tvOS using Swift 3.0

Basic app, this is the code in the view controller... I want to remove the

CAShapeLayer
after it has faded out. The animation works perfectly, but the completion method
animationDidStop
never gets called?

Want to use
override func animationDidStop
method, but it won't compile. Gives me the error "method does not override any method from its superclass" which is wrong surely,
animationDidStop
is a member of
CAAnimation
class.

What is wrong with this code? I could fix this with a timer or something I guess, but it a fudge.

import UIKit
import QuartzCore


class ViewController: UIViewController, CALayerDelegate, CAAnimationDelegate {

var shapeLayer = CAShapeLayer()


override func viewDidLoad() {
super.viewDidLoad()
highlight(XCord: 100, YCord: 100)
clearhighlight()
// Do any additional setup after loading the view, typically from a nib.
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}

func highlight(XCord: CGFloat, YCord: CGFloat) {
DispatchQueue.main.async {
let circlePath = UIBezierPath(arcCenter: CGPoint(x: XCord,y: YCord), radius: CGFloat(20), startAngle: CGFloat(0), endAngle:CGFloat(M_PI * 2), clockwise: true)

self.shapeLayer.path = circlePath.cgPath

//change the fill color
//shapeLayer.fillColor = UIColor.clear.cgColor
self.shapeLayer.fillColor = UIColor.red.cgColor
self.shapeLayer.opacity = 0.5
self.shapeLayer.fillRule = kCAFillRuleEvenOdd

//you can change the stroke color
self.shapeLayer.strokeColor = UIColor.red.cgColor
//you can change the line width
self.shapeLayer.lineWidth = 3.0

DispatchQueue.main.async {
self.view.layer.addSublayer(self.shapeLayer)
}
}
}

func clearhighlight() {
DispatchQueue.main.async {
let fadeInAndOut = CABasicAnimation(keyPath: "opacity")
fadeInAndOut.duration = 10.0;
//fadeInAndOut.autoreverses = true;
fadeInAndOut.repeatCount = 1
fadeInAndOut.fromValue = 1.0
fadeInAndOut.toValue = 0.0
fadeInAndOut.isRemovedOnCompletion = true
fadeInAndOut.fillMode = kCAFillModeForwards;
//self.view.layer.delegate = self
self.shapeLayer.delegate = self
self.shapeLayer.add(fadeInAndOut, forKey: "fadeOut")
self.shapeLayer.setNeedsDisplay()
}
}

func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
print("animationDidStop")
DispatchQueue.main.async {
self.shapeLayer.removeFromSuperlayer()
}
}



}

Rob Rob
Answer

You are setting the delegate of the shape layer:

self.shapeLayer.delegate = self

But if you wanted animationDidStop to be called, you have to set the delegate of the animation, not of the layer:

fadeInAndOut.delegate = self

You say:

Want to use override func animationDidStop method, but it won't compile. Gives me the error "method does not override any method from its superclass" which is wrong surely, animationDidStop is a member of CAAnimation class.

You are implementing this in your view controller and UIViewController does not provide a base class implementation of animationDidStop, so there is nothing to override.

The animationDidStop is a method defined by the CAAnimationDelegate protocol, so (a) the view controller should declare its conformance to that protocol; and (b) do not use the override keyword.

Comments