Creating iOS Apps without Storyboard – Part 2

Handling Size Classes from Code

Size classes are used to categorise devices into different sections. This allows us to perform different actions based on the size class. Size classes handle variation based on orientation and screen size. This can easily be determined using a built in function that we need to override.

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)

Every UIViewController has a property called traitCollection which gives us a lot of information related to the size class of the device such as orientation, device category (Pad, Phone, CarPlay, Tv), support for force touch and so on.
By comparing the value of this property we can easily determine all these values and take appropriate action. Let us implement this and see.


You can use any of the projects created earlier. In fact, you can add this to all the projects if you wish.

  1. Start off by switching to the ViewController.swift file.
  2. Add an extension for the ViewController class.
  3. Implement the override for the traitCollectionDidChange method.
extension ViewController
{
    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) 
    {
        super.traitCollectionDidChange(previousTraitCollection)
    }
}

4. We will now be implementing the code in here. Let us add a trait for the Compact-Compact size class. Add the following lines in the function we just implemented.

//Size classes
if self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClass.compact && self.traitCollection.verticalSizeClass == UIUserInterfaceSizeClass.compact
{
    //Compact - Compact
    appTitle.font       =   UIFont(name: "Gill Sans", size: 18.0)
}

Let us analyse this.

self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClass.compact

We are accessing the traitCollection property of the ViewController and examining its horizontal size class to see if it is compact.

self.traitCollection.verticalSizeClass == UIUserInterfaceSizeClass.compact

We do the same thing for the vertical size class. If both the conditions are satisfied then we will change the appTitle font. In fact we will be having different fonts for different size classes.

5. Write the following code after the if statement.

else if self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClass.compact && self.traitCollection.verticalSizeClass == UIUserInterfaceSizeClass.regular
{
    //Compact - Regular
    appTitle.font       =   UIFont(name: "Gill Sans", size: 20.0)
}
else if self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClass.regular && self.traitCollection.verticalSizeClass == UIUserInterfaceSizeClass.compact
{
    //Regular - Compact
    appTitle.font       =   UIFont.boldSystemFont(ofSize: 20.0)
}
else if self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClass.regular && self.traitCollection.verticalSizeClass == UIUserInterfaceSizeClass.regular
{
    //Regular - Regular
    appTitle.font      =   UIFont.boldSystemFont(ofSize: 24.0)
}
        
//Hide the picker for compact height devices
if self.traitCollection.verticalSizeClass == UIUserInterfaceSizeClass.compact
{
    agePicker.isHidden  = true
}
else if self.traitCollection.verticalSizeClass == UIUserInterfaceSizeClass.regular
{
    agePicker.isHidden  = false
}

We have also added a variation to the agePicker indicating that it is to be hidden for a compact height device.
6. Now we will change the stackSpacing value for different device categories. You may have to change the variable declaration of stackSpacing to var instead of a let.

//Device type
if self.traitCollection.userInterfaceIdiom == UIUserInterfaceIdiom.pad
{
    //iPad
    stackSpacing        = 40.0
}
else if self.traitCollection.userInterfaceIdiom == UIUserInterfaceIdiom.carPlay
{
    //CarPlay
    stackSpacing        = 20.0
}
else if self.traitCollection.userInterfaceIdiom == UIUserInterfaceIdiom.phone
{
    //iPhone
    stackSpacing        = 20.0
}
else if self.traitCollection.userInterfaceIdiom == UIUserInterfaceIdiom.tv
{
    //Apple TV
    stackSpacing        = 50.0
}

7. Finally we will add some code to check if the device is a force touch device or a device with a display scale of 2.0

//UITraitCollection
let forceToucDevice : UITraitCollection = UITraitCollection(forceTouchCapability: UIForceTouchCapability.available)
        
let displayScaleCollection : UITraitCollection = UITraitCollection(displayScale: 2.0)
        
if self.traitCollection.containsTraits(in: forceToucDevice)
{
    print("It is a force touch device")
}
        
if self.traitCollection.containsTraits(in: displayScaleCollection)
{
    print("It is a 2x scale display.")
}

8. Run the code see what comes up. Play around with the different values and check to see if you get the desired results.

One thought on “Creating iOS Apps without Storyboard – Part 2

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s