【问题标题】:UIViewPropertyAnimator stop repeatingUIViewPropertyAnimator 停止重复
【发布时间】:2020-01-17 20:47:15
【问题描述】:

我在 Factory 类中有这段代码,用于返回 UIViewPropertyAnimators 以便在何时何地使用:

class AnimatorFactory {

    @discardableResult
    static func spinSpindle(spindle: UIView) -> UIViewPropertyAnimator {
        let spinSpindleAnimator = UIViewPropertyAnimator(duration: 1.0, curve: .linear)

        spinSpindleAnimator.addAnimations {
            spindle.transform = CGAffineTransform(rotationAngle: .pi)
        }
        spinSpindleAnimator.addCompletion{ position in
            print("spinSpindle.complete: \(position.rawValue)")
            spindle.transform = .identity
            self.spinSpindle(spindle: spindle)
        }
        spinSpindleAnimator.startAnimation()

        return spinSpindleAnimator
    }
...

代码创建了一个UIViewPropertyAnimator,它允许一个永久的动画视图(一个不断旋转和旋转的视图)。它通过在完成块中再次调用自身来做到这一点。我现在遇到的问题是我无法使用UIViewPropertyAnimator.stopAnimation(true) 停止动画。

stopAnimation(_ withoutFinishing:) 值中的true 旨在确保动画返回到UIViewAnimatingState.inactive 状态,而无需使用finishAnimation(at finalPosition:) 执行任何清理。

当我调用stopAnimation(true) 时,动画不会停止。它是这样调用的:

    print("\(spindleAnimator.description)")
    spindleAnimator.stopAnimation(true)
    print("\(spindleAnimator.description)")

以上代码由用户点击动画视图触发并输出:

<UIViewPropertyAnimator(0x600001c1c100) [inactive] interruptible>
<UIViewPropertyAnimator(0x600001c1c900) [inactive] interruptible>

对我来说,这表明spindleAnimator 指的是不同的UIViewPropertyAnimator,因为AnimatorFactory.spinSpindle(spindle:) 静态方法中的“递归”调用。我可能弄错了。

基本上,我正在寻求帮助,以创建一个真正互动和重复的动画。到目前为止,我一直遇到令人难以置信的麻烦,但我不会抱怨,因为我学到了很多东西。但是,我需要一些帮助,通过找到一个有效的 stopAnimation(withoutFinishing:) 电话来将它们联系在一起。

谢谢!

编辑:

另一个有趣的事实是,如果我在主轴完成第一次旋转之前(换句话说,在执行完成块之前)单击主轴,我可以停止动画。这让我相信对spinSpindle(spindle:) 的“递归”调用会创建另一个我无法调用stopAnimation(withoutFinishing:) 的UIViewPropertyAnimator。虽然,我不认为我明白这是怎么回事......

我通过在每次调用 spinSpindle(spindle:) 时打印 spinSpindleAnimator.description 来测试这个理论:

class AnimatorFactory {

    @discardableResult
    static func spinSpindle(spindle: UIView) -> UIViewPropertyAnimator {
        let spinSpindleAnimator = UIViewPropertyAnimator(duration: 1.0, curve: .linear)

        spinSpindleAnimator.addAnimations {
            spindle.transform = CGAffineTransform(rotationAngle: .pi)
        }
        spinSpindleAnimator.addCompletion{ position in
            print("(\(spinSpindleAnimator.description)) spinSpindle.complete: \(position.rawValue)")
            spindle.transform = .identity
            self.spinSpindle(spindle: spindle)
        }
        spinSpindleAnimator.startAnimation()

        return spinSpindleAnimator
    }

它给了

(<UIViewPropertyAnimator(0x600001b20300) [unknown] running interruptible>) spinSpindle.complete: 0
(<UIViewPropertyAnimator(0x600001b28b00) [unknown] running interruptible>) spinSpindle.complete: 0
(<UIViewPropertyAnimator(0x600001b38600) [unknown] running interruptible>) spinSpindle.complete: 0
(<UIViewPropertyAnimator(0x600001b31000) [unknown] running interruptible>) spinSpindle.complete: 0
(<UIViewPropertyAnimator(0x600001b38300) [unknown] running interruptible>) spinSpindle.complete: 0
(<UIViewPropertyAnimator(0x600001b38600) [unknown] running interruptible>) spinSpindle.complete: 0
(<UIViewPropertyAnimator(0x600001b38700) [unknown] running interruptible>) spinSpindle.complete: 0
(<UIViewPropertyAnimator(0x600001b20600) [unknown] running interruptible>) spinSpindle.complete: 0
...

证实我的怀疑。

【问题讨论】:

    标签: ios uiviewpropertyanimator


    【解决方案1】:

    您无法停止动画,因为您持有 UIViewPropertyAnimator 的第一个对象,该对象由您的函数创建并返回,但是您的函数的这一行每次都会创建 UIViewPropertyAnimator 的新对象

    self.spinSpindle(spindle: spindle)
    

    并且您没有将此对象持有/归还到任何地方。 您总是对从函数返回的第一个对象调用 stopAnimation 函数。这就是为什么您可以在主轴完成第一次旋转之前而不是在调用完成块之后单击主轴之前停止动画的原因。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多