Подтвердить что ты не робот

Дождитесь завершения анимации Swift перед выполнением кода

Я пытаюсь оживить UIImageView, а затем скрыть представление изображения после завершения анимации. Однако изображение будет скрыто до завершения анимации. Я посмотрел на подобные вопросы, и они рекомендуют внедрить прослушиватель анимации или выполнить скрытый код в коде анимации после завершения, но я не уверен, как это повлиять на функцию shakeView() ниже.

Как показать анимацию встряхивания и скрыть представление изображения только после завершения анимации?

Анимация вызывается с использованием следующего кода:

shakeView(image1!)
shakeView(image2)
image1!.hidden = true
image2.hidden = true

Сама функция анимации выглядит так:

func shakeView(iv: UIImageView){
    var shake:CABasicAnimation = CABasicAnimation(keyPath: "position")
    shake.duration = 0.1
    shake.repeatCount = 2
    shake.autoreverses = true

    var from_point:CGPoint = CGPointMake(iv.center.x - 5, iv.center.y)
    var from_value:NSValue = NSValue(CGPoint: from_point)

    var to_point:CGPoint = CGPointMake(iv.center.x + 5, iv.center.y)
    var to_value:NSValue = NSValue(CGPoint: to_point)

    shake.fromValue = from_value
    shake.toValue = to_value
    iv.layer.addAnimation(shake, forKey: "position")
}
4b9b3361

Ответ 1

Вы можете использовать CATransaction для вызова блока завершения после завершения анимации.

func shakeView(iv: UIImageView){

    CATransaction.begin()
    CATransaction.setCompletionBlock({
        iv.hidden = true
    })
    var shake:CABasicAnimation = CABasicAnimation(keyPath: "position")
    shake.duration = 0.1
    shake.repeatCount = 21
    shake.autoreverses = true

    var from_point:CGPoint = CGPointMake(iv.center.x - 5, iv.center.y)
    var from_value:NSValue = NSValue(CGPoint: from_point)

    var to_point:CGPoint = CGPointMake(iv.center.x + 5, iv.center.y)
    var to_value:NSValue = NSValue(CGPoint: to_point)

    shake.fromValue = from_value
    shake.toValue = to_value
    iv.layer.addAnimation(shake, forKey: "position")
    CATransaction.commit()
}

Или вы также можете группировать обе анимации вместе в CATransaction следующим образом.

func shakeView(iv: UIImageView){
    var shake:CABasicAnimation = CABasicAnimation(keyPath: "position")
    shake.duration = 0.1
    shake.repeatCount = 21
    shake.autoreverses = true

    var from_point:CGPoint = CGPointMake(iv.center.x - 5, iv.center.y)
    var from_value:NSValue = NSValue(CGPoint: from_point)

    var to_point:CGPoint = CGPointMake(iv.center.x + 5, iv.center.y)
    var to_value:NSValue = NSValue(CGPoint: to_point)

    shake.fromValue = from_value
    shake.toValue = to_value
    iv.layer.addAnimation(shake, forKey: "position")
}

override func viewDidLoad() {
    CATransaction.begin()

    CATransaction.setCompletionBlock({
        self.image1.hidden = true
        self.image2.hidden = true
    })
    shakeView(image1)
    shakeView(image)
  CATransaction.commit()
}

Ответ 2

Как упоминалось в комментарии к Paulw11, вы можете использовать метод animationDidStop:, упомянутый в документах. Кроме того, вы должны добавить к вам ключ CABasicAnimation/CAAnimation объектов, чтобы ваш метод animationDidStop: знал, какой из них был завершен.

Итак, в вашем методе shake добавьте пару value-key для идентификации анимации и установите делегат в self, ex:

func shakeView(iv: UIImageView){

    var shake:CABasicAnimation = CABasicAnimation(keyPath: "position")
    shake.duration = 0.1
    shake.repeatCount = 2
    shake.autoreverses = true

    // Add these two lines:
    shake.setValue("shake", forKey: "animationID")
    shake.delegate = self

    // ...

Затем добавьте метод делегата animationDidStop:, чтобы предупредить вас о завершении анимации, чтобы вы могли начать выполнять свой код:

override func animationDidStop(anim: CAAnimation!, finished flag: Bool) {
    // Unwrap the optional value for the key "animationID" then
    // if it equal to the same value as the relevant animation,
    // execute the relevant code
    if let animationID: AnyObject = anim.valueForKey("animationID") {
        if animationID as NSString == "shake" {
            // execute code
        }
    }
}