Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.3k views
in Technique[技术] by (71.8m points)

iphone - How to remove a layer when its animation completes?

I am making an iOS App. I have several CALayer objects that eventually will be deleted by a (shrinking) animation. When the animation is completed, and animationDidStop:finished is invoked, I would like to remove the CALayer object from the super view and delete it.

  1. But how can I get the CALayer object in animationDidStop:finished? I would have guessed that the CAanimation-object had a pointer to the layer, but I can't find it in the doc.
  2. Is there a better way to handle the issue? (Actually, I have several animation objects added to the same layer, and, ideally, I would like to remove the layer only when the last animation completes)
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It's been a long time since this question has been answered, however i'll try and add a more swifty solution, in case anybody is still looking for a more clean solution nowadays.

If everything you're interested in is simply remove the layer as soon as the CAAnimation is finished, you can assign the animation's delegate to a simple NSObject that holds a reference to the target layer and waits for the animation callback in order to dismiss it.

Let's call this helper object LayerRemover:

class LayerRemover: NSObject, CAAnimationDelegate {
    private weak var layer: CALayer?

    init(for layer: CALayer) {
        self.layer = layer
        super.init()
    }

    func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
        layer?.removeFromSuperlayer()
    }
}

Everything this object does is receiving a CALayer reference via initializer and waiting for the animationDidStop callback before removing the layer. At this point, as soon as the CAAnimation that's retaining it via the delegate property is deinitialized, the Layer remover gets purged too.

Now, all you have to do is actually instatiate this remover and use it:

let layer = CAShapeLayer()
layer.path = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: 200, height: 100)).cgPath
let myAnimation = CABasicAnimation(keyPath: "strokeEnd")
...
myAnimation.delegate = LayerRemover(for: layer)

That's it!

Please note that you don't have to retain any reference to the LayerRemover object since from the Apple documentation we can read that

The delegate object is retained by the receiver. This is a rare exception to the memory management rules described in Advanced Memory Management Programming Guide.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...