CAShapeLayer奇怪的动画行为

时间:2017-03-08 10:52:30

标签: ios animation core-animation cashapelayer

我正在尝试创建一个动画,其中当用户拖动UIView时两条线淡出并在用户释放拖动时淡入淡出。
因此,我有两个函数undrawLines(在平移手势启动时调用)和redrawLines(在平移手势结束时调用),由我的UIPanGestureRecognizer动作处理程序调用。

func undrawLines() {

    line1.opacity = 0.0
    line2.opacity = 0.0

    line1.removeAllAnimations()
    line2.removeAllAnimations()

    let opacityLine = CABasicAnimation(keyPath: "opacity")
    opacityLine.fromValue = 1.0
    opacityLine.toValue = 0.0
    opacityLine.duration = 0.15

    line1.add(opacityLine, forKey: "disappearLine1")
    line2.add(opacityLine, forKey: "disappearLine2")

    DispatchQueue.main.asyncAfter(deadline: .now() + 0.3, execute: {
        mill.line1.removeFromSuperlayer()
        mill.line2.removeFromSuperlayer()
    })
}

func redrawLines() {

    line1.opacity = 1.0
    line2.opacity = 1.0

    print("redraw")
    line1.removeAllAnimations()
    line2.removeAllAnimations()

    self.layer.addSublayer(line1)
    self.layer.addSublayer(line2)

    let opacityLine = CABasicAnimation(keyPath: "opacity")
    opacityLine.fromValue = 0.0
    opacityLine.toValue = 1.0
    opacityLine.duration = 0.15

    line1.add(opacityMill, forKey: "appearLine1")
    line2.add(opacityMill, forKey: "appearLine2")
}

问题是当redrawLines动画仍在运行时调用undrawLines时,这些行会显示奇怪的行为,不透明度为0。 这是一个演示,第一部分展示它应该如何,第二部分显示错误:

enter image description here

1 个答案:

答案 0 :(得分:1)

我相信你的问题是你的完成处理程序的竞争条件:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.3, execute: {
    mill.line1.removeFromSuperlayer()
    mill.line2.removeFromSuperlayer()
})

如果您的用户发布,因此{0.3}在0.3秒超时之前被调用,则仍然会调用它并删除这些行。

您可能希望保留一个指示当前意图的状态标志,然后在异步回调中检查它:

redrawLines

您显然需要将实例var func undrawLines() { self.linesHidden = true // update state line1.opacity = 0.0 line2.opacity = 0.0 line1.removeAllAnimations() line2.removeAllAnimations() let opacityLine = CABasicAnimation(keyPath: "opacity") opacityLine.fromValue = 1.0 opacityLine.toValue = 0.0 opacityLine.duration = 0.15 line1.add(opacityLine, forKey: "disappearLine1") line2.add(opacityLine, forKey: "disappearLine2") DispatchQueue.main.asyncAfter(deadline: .now() + 0.3, execute: { [weak self] in if self?.linesHidden == true { // check this is still what we want to do mill.line1.removeFromSuperlayer() mill.line2.removeFromSuperlayer() } }) } func redrawLines() { self.linesHidden = false // update state line1.opacity = 1.0 line2.opacity = 1.0 print("redraw") line1.removeAllAnimations() line2.removeAllAnimations() self.layer.addSublayer(line1) self.layer.addSublayer(line2) let opacityLine = CABasicAnimation(keyPath: "opacity") opacityLine.fromValue = 0.0 opacityLine.toValue = 1.0 opacityLine.duration = 0.15 line1.add(opacityMill, forKey: "appearLine1") line2.add(opacityMill, forKey: "appearLine2") } 添加到类中以使其工作:)