NEW: Join my free 100 Days of SwiftUI challenge today! >>

How to animate when your size class changes: willTransition(to:)

Swift version: 5.1

Paul Hudson    @twostraws   

A size class change is usually triggered by your user rotating their device, but it can also happen for example when using the new iOS 9.0 multitasking to adjust window splits. Your UI needs to look great in all size classes it supports, which means you either create multiple variations of your layouts inside Interface Builder (this is the preferred route) or you make changes in code.

More often than not, I find myself mixing approaches: I do the vast majority of work inside IB, then make minor changes by hand inside the willTransition(to:) method. When this is called, you'll be given a UIViewControllerTransitionCoordinator object (yes, that's an extremely long name!) to work with, which allows you to animate your changes as needed.

To give you a very visible demonstration of how this works, I've written some example code below that adjusts the background color of the current view. You should run this using the iOS simulator using an iPhone rather than an iPad. The reason that this requires the iPhone simulator rather than the iPad simulator is that iPads have the same size classes in portrait and landscape, which makes the changes harder to spot.

Anyway, put this code into a view controller, then try it on an iPhone. When you rotate the simulator, the screen will change between red and blue, or green and blue, depending on the rotation. The important thing is that the change is animated because it's placed inside a call to animate(alongsideTransition:), which automatically makes your animation match the rotation animation.

Using this method requires two closures: the first is where you make the changes you want to animate, and the second is code to be run when the animation completes. So, when the new vertical size class is compact, the screen will animate from blue to red, then jump back to blue. I realize this isn't directly useful in your own apps, but that's because you'll want to make your own changes – just take the code below and replace the background color changes with your own logic.

override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
    super.willTransition(to: newCollection, with: coordinator)

    coordinator.animate(alongsideTransition: { [unowned self] _ in
        if newCollection.verticalSizeClass == .compact {
            self.view.backgroundColor = UIColor.red
        } else {
            self.view.backgroundColor = UIColor.green
        }
    }) { [unowned self] _ in
        self.view.backgroundColor = UIColor.blue
    }
}

LEARN SWIFTUI FOR FREE I have a massive, free SwiftUI video collection on YouTube teaching you how to build complete apps with SwiftUI – check it out!

Available from iOS 8.0

Similar solutions…

About the Swift Knowledge Base

This is part of the Swift Knowledge Base, a free, searchable collection of solutions for common iOS questions.

BUY OUR BOOKS
Buy Pro Swift Buy Swift Design Patterns Buy Testing Swift Buy Hacking with iOS Buy Swift Coding Challenges Buy Swift on Sundays Volume One Buy Server-Side Swift (Vapor Edition) Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Advanced iOS Volume Three Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with macOS Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Server-Side Swift (Kitura Edition) Buy Beyond Code

Was this page useful? Let us know!

Average rating: 2.3/5