web-dev-qa-db-fra.com

Attendez que Swift se termine avant d'exécuter le code

J'essaie d'animer une UIImageView, puis de masquer la vue de l'image une fois l'animation terminée. Cependant, l'image est masquée avant la fin de l'animation. J'ai regardé des questions similaires et ils recommandent d'implémenter un écouteur d'animation ou d'exécuter le code .hidden dans le code d'animation à la fin, mais je ne sais pas comment affecter cela dans la fonction shakeView () ci-dessous.

Comment afficher l'animation de tremblement et masquer la vue de l'image uniquement une fois l'animation terminée?

L'animation est appelée à l'aide du code suivant:

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

La fonction d'animation elle-même ressemble à ceci:

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")
}
29
zeeshan

Vous pouvez utiliser un CATransaction pour appeler un bloc d'achèvement une fois l'animation terminée.

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()
}

Ou vous pouvez également regrouper les deux animations dans un CATransaction comme suit.

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()
}
66
rakeshbs

Comme Paulw11 y a fait allusion dans son commentaire, vous pouvez utiliser le animationDidStop: méthode mentionnée dans la documentation. Mais en plus, vous devez ajouter une clé pour vous CABasicAnimation/CAAnimation objets tels que votre animationDidStop: la méthode sait laquelle en particulier s'est terminée.

Donc, dans votre méthode shake, ajoutez une paire valeur-clé pour identifier l'animation et définissez le délégué sur self, par exemple:

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

    // ...

Ajoutez ensuite le animationDidStop: méthode déléguée pour vous avertir de la fin de l'animation afin que vous puissiez commencer à exécuter votre code:

override func animationDidStop(anim: CAAnimation!, finished flag: Bool) {
    // Unwrap the optional value for the key "animationID" then
    // if it's 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
        }
    }
}
15
Lyndsey Scott