2

我在 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).

trueinstopAnimation(_ withoutFinishing:)值旨在确保动画返回到状态,而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引用不同。我可能弄错了。UIViewPropertyAnimatorAnimatorFactory.spinSpindle(spindle:)

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

谢谢!

编辑:

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

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

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
...

证实了我的怀疑。

4

1 回答 1

3

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

self.spinSpindle(spindle: spindle)

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

于 2020-01-20T13:20:02.023 回答