Use CADisplayLink
since it is specifically built for this purpose. In the documentation, it says:
Once the display link is associated with a run loop, the selector on the target is called when the screen’s contents need to be updated.
For me I had a bar that fills up, and as it passed a certain mark, I had to change the colors of the view above that mark.
This is what I did:
let displayLink = CADisplayLink(target: self, selector: #selector(animationDidUpdate))
displayLink.frameInterval = 3
displayLink.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSDefaultRunLoopMode)
UIView.animateWithDuration(1.2, delay: 0.0, options: [.CurveEaseInOut], animations: {
self.viewGaugeGraph.frame.size.width = self.graphWidth
self.imageViewGraphCoin.center.x = self.graphWidth
}, completion: { (_) in
displayLink.invalidate()
})
func animationDidUpdate(displayLink: CADisplayLink) {
let presentationLayer = self.viewGaugeGraph.layer.presentationLayer() as! CALayer
let newWidth = presentationLayer.bounds.width
switch newWidth {
case 0 ..< width * 0.3:
break
case width * 0.3 ..< width * 0.6:
// Color first mark
break
case width * 0.6 ..< width * 0.9:
// Color second mark
break
case width * 0.9 ... width:
// Color third mark
break
default:
fatalError("Invalid value observed. (newWidth) cannot be bigger than (width).")
}
}
In the example, I set the frameInterval
property to 3
since I didn't have to rigorously update. Default is 1
and it means it will fire for every frame, but it will take a toll on performance.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…