Search code examples
iosswiftios8xcode6uilabel

Fade in/out label with strings from array


func setOverlayTitle() {
    self.overlayLogo!.text = "Welcome"
    var hello: [String] = ["Bon Jour", "GUTEN\nMORGEN", "BONJOUR", "HOLA", "안녕하세요", "BUENOS DÍAS", "BUONGIORNO", "早安", "おはよう", "गुड मॉर्निंग"]

    for (var i = 1; i < hello.count-1; i++) {
    UIView.animateWithDuration(1.0, delay: 2.0, options: UIViewAnimationOptions.CurveEaseOut, animations: {
        self.overlayLogo!.alpha = 0.0
        }, completion: {
            (finished: Bool) -> Void in
            println(i)
            self.overlayLogo!.text = hello[i]

            // Fade in
            UIView.animateWithDuration(1.0, delay: 0.0, options: UIViewAnimationOptions.CurveEaseIn, animations: {
                self.overlayLogo!.alpha = 1.0
                }, completion: nil)
    })
  }

}

I have the following code and I'm trying to iterate through the array "hello" while fade in/out the label with a 2 second delay. But this code won't work! Currently it just prints the number 9, 9 times and fades in/out only once


Solution

  • The issue is caused by the for loop you are using there. You can't get the desired behavior in that way. for loop won't wait for your label animation to complete before starting the next iteration. Instead of that, you can make a recursive call from the method itself after each animation cycle completes.

    You need to declare a variable in your class and implement the method like below:

    Update for Swift 5 and Above:

    var iterator = 1;
        
    override func viewDidLoad() {
            
       super.viewDidLoad()
       self.lblAnime!.text = "Welcome"
       setOverlayTitle()
    }
        
    func setOverlayTitle() {
       let hello: [String] = ["Bon Jour", "GUTEN\nMORGEN", "BONJOUR", "HOLA", "안녕하세요", "BUENOS DÍAS", "BUONGIORNO", "早安", "おはよう", "गुड मॉर्निंग"]
            
       UIView.animate(withDuration: 1.0, delay: 2.0, options: UIView.AnimationOptions.curveEaseOut, animations: {
                
          self.lblAnime!.alpha = 0.0
       }, completion: { (finished: Bool) -> Void in
                
          self.lblAnime!.text = hello[self.iterator]
                
          // Fade in
          UIView.animate(withDuration: 1.0, delay: 0.0, options: UIView.AnimationOptions.curveEaseIn, animations: {
                    
             self.lblAnime!.alpha = 1.0
          }, completion: { (finished: Bool) -> Void in
                    
             self.iterator += 1
             if self.iterator < hello.count {
                self.setOverlayTitle();
             }
          })
       })
    }
    

    Original Answer (Older versions of Swift):

    var iterator = 1;
    
    override func viewDidLoad()
    {
        
        super.viewDidLoad()
        self.lblAnime!.text = "Welcome"
        setOverlayTitle()
    }
    
    func setOverlayTitle()
    {
        
        var hello: [String] = ["Bon Jour", "GUTEN\nMORGEN", "BONJOUR", "HOLA", "안녕하세요", "BUENOS DÍAS", "BUONGIORNO", "早安", "おはよう", "गुड मॉर्निंग"]
        
        UIView.animateWithDuration(1.0, delay: 2.0, options: UIViewAnimationOptions.CurveEaseOut, animations:
           {
                self.lblAnime!.alpha = 0.0
           },
           completion:
           {(finished: Bool) -> Void in
                println(self.iterator)
                self.lblAnime!.text = hello[self.iterator]
                    
                // Fade in
                UIView.animateWithDuration(1.0, delay: 0.0, options: UIViewAnimationOptions.CurveEaseIn, animations:
                    {
                         self.lblAnime!.alpha = 1.0
                    },
                    completion:
                    {(finished: Bool) -> Void in
                         self.iterator++
                            
                         if self.iterator < hello.count
                         {
                             self.setOverlayTitle();
                         }
                    })
           })
    }