Blog

Animate constraints with a simple UIView extension in Swift

01 Apr, 2015
Xebia Background Header Wave

iOS Developers that are getting started with Auto Layout for the first time often run in trouble once they try to animate their views. The solution is quite simple, but in this post I’ll create a simple Swift extension that makes it even easier.

When you don’t use Auto Layout, you need to make the changes to your UIView frames inside an animations block. Those changes will then be animated. So without knowing any better, you would do the same for your Auto Layout constraints, which means changing the constraint constants inside the animations block. This doesn’t work however, and a quick google search on "how to animate constraints" shows that your need only need to call view.layoutIfNeeded within the animations block after you’ve made the changes to the constraints.
A simple example of this:
[objc]
heightConstraint.constant = 100
UIView.animateWithDuration(0.5, animations: { [weak self] in
self?.view.layoutIfNeeded() ?? ()
})
[/objc]
it’s necessary to call it this wat since updating constants of constraints doesn’t immediately change the frames of the views affected by those constraints. That’s why we need to call layoutIfNeeded, to update all the frames of our views.
Since we just want to be always safe with memory management we’ll use a weak reference of self within the closure, even though we know the closure is not retained after the animation runs and the view will not be deallocated before the animation finishes (it’s good practice to use weak whenever you can to avoid memory related problems).
The above sample is not a lot of code, but each time you want to animate something with constraints you need to write the same thing. Wouldn’t it be much easier to write the following instead?
[objc]
heightConstraint.constant = 100
view.animateConstraintWithDuration()
[/objc]
We can achieve that by adding an extension to UIView:
[objc]
extension UIView {
func animateConstraintWithDuration(duration: NSTimeInterval = 0.5) {
UIView.animateWithDuration(duration, animations: { [weak self] in
self?.layoutIfNeeded() ?? ()
})
}
}
[/objc]
Default values for the method parameters makes this even nicer. Above we used 0.5 as default duration but of course you can fill in duration you want when calling the method. Also we can add parameters with default values for the other parameters that animateWithDuration has.

The final extension

[objc]
extension UIView {
func animateConstraintWithDuration(duration: NSTimeInterval = 0.5, delay: NSTimeInterval = 0.0, options: UIViewAnimationOptions = nil, completion: ((Bool) -> Void)? = nil) {
UIView.animateWithDuration(duration, delay:delay, options:options, animations: { [weak self] in
self?.layoutIfNeeded() ?? ()
}, completion: completion)
}
}
[/objc]
There we have it. An extremely simple extension method that not only saves us a little bit of code each time we need to animate constraints but is also makes the code a lot cleaner since the name of the method clearly indicates what it does, as apposed to the layoutIfNeeded method within an animations block.

Questions?

Get in touch with us to learn more about the subject and related solutions

Explore related posts