Search code examples
iosuiviewautolayoutuiviewanimation

About iOS Constraint update Animation - Animation block + layoutIfNeeded


Hello I'm trying to understand view update cycle

I could understand almost things, but there are some mysterious things

I learn that animation blocks are also triggered at update cycle

To try to understand layoutIfNeeded in Animation block, I wrote some sample codes like below

class MyView: UIView {
    override func layoutSubviews() {
        super.layoutSubviews()
        print("Layout Subviews")
    }
}
class ViewController: UIViewController {

    @IBOutlet weak var blueHeight: NSLayoutConstraint!

    @IBAction func heightPressed(_ sender: AnyObject) {

        if self.blueHeight.constant == 25.0 {
            self.blueHeight.constant = self.view.bounds.height - 100.0
        } else {
            self.blueHeight.constant = 25.0
        }

        self.view.setNeedsLayout()
        UIView.animate(withDuration: 2.0, animations: {
            print("animation block")
            self.view.layoutIfNeeded() // ----- **
        }) { (_) in
            print("animation ended")
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

The output was like this

"Layout Subviews"
"Layout Subviews" ---- because of initial settings 
"Animation block"
"Layout Subviews"
"Animation ended"

but when i changed layoutIfNeeded to setNeedsLayout the output is changed

"Layout Subviews"
"Layout Subviews" ---- because of initial settings 
"Animation block"
"Animation ended"
"Layout Subviews"

so i understand that animation block executed first and view updates, so animation block has higher priority than view's update in update cycle

is that right? If i was wrong, i want to understand relationship between view's update cycles and animation block


Solution

  • What is inside the animation block, if it is animatable, does not run until animation time at the end of the transaction.

    layoutIfNeeded counts as animatable. What it does in an animation block is: it causes the changes in frame etc. performed in code or by autolayout in layoutSubviews to be animated rather than immediate.

    Basically, this is a way of wrapping the next layout moment in an animation.