是否使用自定义绘图代码drawLayer(_:inContext:)或drawRect(_:)(或同时使用)自定义绘图代码取决于是否需要在动画化图层属性时访问其当前值。
今天,当实现自己的Label类时,我在与这两个函数相关的各种渲染问题上苦苦挣扎。在检查了文档之后,进行了反复试验,反编译了UIKit并检查了Apple的Custom Animatable Properties示例,我对它的工作方式有了很好的了解。
drawRect(_:)
如果不需要在动画期间访问图层/视图属性的当前值,则可以简单地使用drawRect(_:)它执行自定义绘图。一切都会正常。
override func drawRect(rect: CGRect) {
    
}
drawLayer(_:inContext:)
例如,假设您要backgroundColor在自定义绘图代码中使用:
override func drawRect(rect: CGRect) {
    let colorForCustomDrawing = self.layer.backgroundColor
    
}
在测试代码时,您会注意到 backgroundColor在动画播放过程中该未返回正确的(即当前)值。而是返回最终值(即动画完成时的值)。
为了在动画过程中获得当前值,您必须访问传递给backgroundColor的layer 参数drawLayer(_:inContext:)。而且您还必须吸引context 参数。
知道视图self.layer和layer传递给它的参数drawLayer(_:inContext:)并不总是同一层非常重要!后者可能是前者的副本,并且已经对其属性应用了部分动画。这样,您可以访问飞行中动画的正确属性值。
现在,工程图可以按预期工作:
override func drawLayer(layer: CALayer, inContext context: CGContext) {
    let colorForCustomDrawing = layer.backgroundColor
    
}
但是有两个新问题:setNeedsDisplay()和一些属性,例如backgroundColor和opaque不再对您的视图起作用。UIView不再转发呼叫并更改到其自己的层。
setNeedsDisplay() 仅在您的视图实现时才做某事 drawRect(_:)。函数是否实际执行操作并不重要,但UIKit使用它来确定是否执行自定义绘图。
这些属性可能不再起作用,因为 UIViewdrawLayer(_:inContext:)不再调用自己的实现。
因此,解决方案非常简单。只需调用超类的实现drawLayer(_:inContext:)并实现一个空drawRect(_:):
override func drawLayer(layer: CALayer, inContext context: CGContext) {
    super.drawLayer(layer, inContext: context)
    let colorForCustomDrawing = layer.backgroundColor
    
}
override func drawRect(rect: CGRect) {
    
    
}
概要
使用drawRect(_:)只要你没有这样的属性在动画过程中返回错误值的问题:
override func drawRect(rect: CGRect) {
    
}
如果需要动画化视图/图层属性的当前值,请使用drawLayer(_:inContext:) 和 drawRect(_:):
override func drawLayer(layer: CALayer, inContext context: CGContext) {
    super.drawLayer(layer, inContext: context)
    let colorForCustomDrawing = layer.backgroundColor
    
}
override func drawRect(rect: CGRect) {
    
    
}
     
              
AccelerometerGraph。我猜想是在该代码示例中实现的,drawLayer:inContext:因为除了视图的根层之外,还向该层层次结构添加了一些层,而实际上委托不是UIView实例。