UIViewPropertyAnimator перестать повторяться - PullRequest
2 голосов
/ 17 января 2020

У меня есть этот код в классе 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).

Значение true in stopAnimation(_ 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 относится к другому UIViewPropertyAnimator из-за «рекурсивного» вызова в методе AnimatorFactory.spinSpindle(spindle:) stati c. Я могу ошибаться

По сути, я ищу помощи, чтобы создать действительно интерактивную и повторяющуюся анимацию. До сих пор у меня были невероятные проблемы с этим, но я не буду жаловаться, потому что я многому научился. Тем не менее, мне нужна помощь, чтобы связать все это вместе, найдя работающий 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
...

, подтверждающее мои подозрения.

1 Ответ

2 голосов
/ 20 января 2020

Вы не можете остановить анимацию, потому что вы держите первый объект UIViewPropertyAnimator, который создается и возвращается вашей функцией, но эта строка вашей функции создает каждый раз, когда новый объект UIViewPropertyAnimator

self.spinSpindle(spindle: spindle)

и вы не удерживаете / не возвращаете этот объект никуда. Вы всегда вызываете функцию stopAnimation для первого объекта, который вы вернули из функции. Вот почему вы можете остановить анимацию до того, как щелкнете по шпинделю до того, как он завершит свой первый оборот, а не после вызванного блока завершения.

...