iosswiftuiimageviewuiviewanimationuiviewanimationtransition

How to use completion block for UIView.animate()?


I'm working on a project to learn animations and am having trouble using the completion block for the UIView.animate(withDuration:) func. MY animation is a shoebox that falls from the top of the screen, lands on a pedestal, then opens. Once the box opens I want a UIImageView to come out of the box, grow to full size of the screen and then segue to the next page, but the completion handler that the code for segueing is called before my animation completes and the UIImageView doesn't appear at all.

Here's my code:

override func viewDidAppear(_ animated: Bool) {
            
    UIView.animate(withDuration: 1.5, delay: 0.0, options: .curveEaseInOut,
                   animations: {
                    //Opening the box
                    self.shoeBoxImage.shoeBox.animationImages = self.boxOpeningAnimation
                    self.shoeBoxImage.shoeBox.animationDuration = 1.5
                    self.shoeBoxImage.shoeBox.animationRepeatCount = 1
                    self.shoeBoxImage.shoeBox.contentMode = .scaleAspectFill
        
                    self.shoeBoxImage.shoeBox.startAnimating()
        
                    //set to the final image
                    self.shoeBoxImage.shoeBox.image = UIImage(named: "frame13")
    },completion: {_ in
        let nextPage = UIImageView()
        nextPage.frame = CGRect(origin: self.shoeBoxImage.center, size: CGSize(width: 0.0, height: 0.0))
        nextPage.image = UIImage(named: "FirstLoadBackgroundImg.jpeg")
        nextPage.autoresizesSubviews = true
        self.view.addSubview(nextPage)
        self.view.bringSubviewToFront(nextPage)
        UIView.animate(withDuration: 5.0, animations: {
            nextPage.transform = CGAffineTransform(scaleX: 428, y: 926)
        })
        
        self.performSegue(withIdentifier: "FinishedLoading", sender: self)
    })
}

This is my first time working with animations and programatically creating views so if someone could explain how to make the completion block wait for the animation to complete. In order to make the UIImageView appear and animate then once it's full screen, segue to the next page it would be very much appreciated.


Solution

  • The size is 0, 0. Transforming zero by any scale is still zero. I would advise you to not use transform at all, but rather just set the final frame to be what you want.

    E.g.,

    let startFrame = CGRect(x: view.bounds.midX, y: view.bounds.midY, width: 0, height: 0)
    let endFrame = view.bounds
    
    let imageView = UIImageView(image: ...)
    imageView.contentMode = .scaleAspectFill
    view.addSubview(imageView)
    imageView.frame = startFrame
    UIView.animate(withDuration: 3, delay: 0, options: .curveEaseInOut) {
        imageView.frame = endFrame
    } completion: { _ in
        // do something here
    }
    

    That yields:

    enter image description here


    By the way, the performSegue probably should be inside a completion closure of the inner animate call.