动画期间的 CALayer 使用默认 属性 值而不是当前实例的 属性 值

CALayer during animation is using default property value instead of what should be the current instance's property value

我在 xCode Playground 中重新创建了我的问题,该 Playground 对我 运行 遇到的错误进行了采样(展示往往更善于解释): https://gist.github.com/Wowserman/c1910523ad85cf34d3e08150b65c7074

我的问题是,我的 CALayer class 完美地渲染了它的绘图,在这个 .gif 中你可以看到它第一次渲染时的样子(底部有阴影的绿色)并且很清楚渲染它应该如何,但是一旦我开始动画阴影高度就是问题所在。

我将 shadowHeight 从 12.0 设置为 0.0 并反转该动画,除了 color 属性 管理外,动画效果很好在我无意的情况下更改为默认值(黄色)!

你可以在这张 gif 中看到,图层首先呈现为绿色和阴影(这是有意的),然后当视图被触摸时,图层会动画化阴影的收缩(有意的)但是 color 在动画期间更改为默认值(黄色),一旦完成,它将返回到实例的正确 color 值。在整个动画过程中,动画应该始终是 color 的值。

我检查过 color 属性 永远不会改变,我有一个 didSet 观察者每次改变时打印,它只是改变了在初始化过程中应该是这样。

然后我检查了 CALayerdraw(in ctx:) 方法,那是我看到 color 属性 不同的地方。

我认为另一个可能的问题可能是图层 drawsAsynchronously 是正确的,但在切换它之后我发现它不是问题所在。

我的问题总结:

层的颜色 属性 在动画期间悄悄更改为默认 属性 值,而不是初始化时设置的值,导致不需要的渲染。

color 上的 didSet 观察者中 - 不要调用 display()

您不应该直接调用 display。正如文档所述:

Do not call this method directly. The layer calls this method at appropriate times to update the layer’s content.

改为使用:

self.setNeedsDisplay()

编辑:您的 common() 函数也是如此。

我为有需要的人找到了解决方案。为 CALayer 设置动画时,CALayer 不会发生变化,而是通过使用 CALayer 的 init(layer:).

进行复制

我正在阅读有关此初始化程序 (enter link description here) 的文档,发现在重写内您应该将 layer 的自定义属性复制到新的 CALayer 子类。

public override init(layer: Any) {
    super.init(layer: layer)

    self.common()
    
    guard let overlay = layer as? OverlayLayer else {
        return
    }
    
    self.color = overlay.color
}

如果你好奇的话,这里有一个包含修复的更新要点

https://gist.github.com/Wowserman/ca23d9596f2979effd9cc8fa9e73c893