Search code examples
swiftanimationjquery-animatecgrectcompletion

do a animation with 3 actions in swift


I want my swift code to do a animation with the separate and different actions. That are in sequential order. The first 2 animations work however when I add the 3rd animation it does not work anymore and causes a compile error. You can see the 3rd animation where the comment is. I just want to get all 3 animations to work.

import UIKit

class ViewController: UIViewController {
    
    
    var block1 = UIView()

    var btn = UIButton()
  
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        [block1,btn].forEach{
            $0.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview($0)
        }
   
        block1.backgroundColor = .yellow
 
        btn.backgroundColor = .red
        
        block1.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height * 0.1)
 
        
        btn.frame = CGRect(x: 100, y: 300, width: 100, height: 100)
        btn.backgroundColor = .red
        
        btn.addTarget(self, action: #selector(diverse), for: .touchDown)
    }
    
    @objc func diverse(){
        
        //1
        UIView.animate(withDuration: 1, animations: {
            
            self.block1.frame = CGRect(x: 100, y: 100, width: 100, height: 200)
            self.block1.center = self.view.center
            
        })
        //2
        { done in
            if done {
                UIView.animate(withDuration: 11, animations: {
                    
                    self.block1.frame = CGRect(x: 100, y: 100, width: 22, height: 100)
                    self.block1.center = self.view.center
                    
                })
                
                
                
                
                
            }
        }
        //3 does not work
        { done in
            if done {
                UIView.animate(withDuration: 11, animations: {
                    
                    self.block1.frame = CGRect(x: 100, y: 100, width: 2, height: 100)
                    self.block1.center = self.view.center
                    
                })
                
                
                
                
                
            }
        }
        
        
      
        

        
        
    }
    
    
    }

Solution

  • The documentation for animate(withDuration:animations:completion:) shows its declaration, which is this:

    class func animate(withDuration duration: TimeInterval, 
            animations: @escaping () -> Void, 
            completion: ((Bool) -> Void)? = nil)
    

    The completion argument label takes in a closure, which gets called when the animation finishes.

    UIView.animate(withDuration: 1, animations: {
        self.block1.frame = CGRect(x: 100, y: 100, width: 100, height: 200)
        self.block1.center = self.view.center
    }) { done in /// closure here
    
    }
    

    However, there is no argument label for a second completion closure. That is why

    UIView.animate(withDuration: 1, animations: {
        self.block1.frame = CGRect(x: 100, y: 100, width: 100, height: 200)
        self.block1.center = self.view.center
    }) { done in /// closure here
    
    } { done in /// second closure? Nope.
    
    }
    

    ... does not compile.

    Instead, what you want to do is

    • put the second animation in the completion handler of the first
    • put the third animation in the completion handler of the second
    /// start first animation
    UIView.animate(withDuration: 1, animations: {
        self.block1.frame = CGRect(x: 100, y: 100, width: 100, height: 200)
        self.block1.center = self.view.center
    }) { done in
    
        /// first animation finished, start second
        if done {
            UIView.animate(withDuration: 11, animations: {
                
                self.block1.frame = CGRect(x: 100, y: 100, width: 22, height: 100)
                self.block1.center = self.view.center
                
            }) { done in
    
                /// second animation finished, start third
                if done {
                    UIView.animate(withDuration: 11, animations: {
                        
                        self.block1.frame = CGRect(x: 100, y: 100, width: 2, height: 100)
                        self.block1.center = self.view.center
                        
                    })
                }
    
            }
        }
    }