Size classes and UIViewController

Posted by: admin

Size classes were introduced in iOS 8. This enables developers to abstract actual device models into an arbitrary representation by a combination of a vertical size class and a horizontal size class. This in turn enables a device to have specific layouts and behaviours that are orientation specific. The size classes for each dimension, both horizontal and vertical, are either compact or regular. This currently works great in the majority of cases, but what about the iPad?

The iPad has a horizontal and vertical size class of regular for both portrait and landscape orientations. This information allows us, under the current device range, to easily determine if the device is an iPad/iPad mini or not. However orientation cannot be determined with this information alone.

One solution I came up with is to write a extension/category on UIViewController. It adds a boolean property named isPortrait and two methods named isSizeClassesBothRegular and isSizeClassesCompactWidthRegularHeight.

Swift .swift file

 

import UIKit

 

extension UIViewController {

 

// (readonly) property - can optionally drop the 'get' syntax

 

var isPortrait: Bool {

 

get { let orientationRect = UIScreen.mainScreen().bounds

 

return (orientationRect.size.height > orientationRect.size.width) ? true : false }

 

}

 

// isSizeClassesBothRegular - returns true if both size classes are regular.

 

func isSizeClassesBothRegular() -> Bool {

 

return (self.traitCollection.verticalSizeClass == UIUserInterfaceSizeClass.Regular && self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClass.Regular) ? true : false  }

 

/* Discussion - Use this method to assist with device determination. For example if return value is true then at present it is assumed the device executing the code is an iPad device model. */

 

// isSizeClassesCompactWidthRegularHeight - returns true if size classes are compact width and regular height

 

func isSizeClassesCompactWidthRegularHeight() -> Bool {

 

return (self.traitCollection.verticalSizeClass == UIUserInterfaceSizeClass.Regular && self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClass.Compact) ? true : false }

 

/* Discussion - Use this method to assist with device determination. For example if return value is true then at present it is assumed the device executing the code is an iPhone/iPod Touch device model in portrait orientation. */

 

}

And here’s the same as above written as a category in Objective C.

Objective C .h file

 

#import <UIKit/UIKit.h>

 

@interface UIViewController (BWAdditions)

 

// query orientation

 

@property (readonly) BOOL isPortrait;// return YES for portrait orientation

 

// query size class

 

- (BOOL)isSizeClassesBothRegular;// return YES for iPad

 

- (BOOL)isSizeClassesCompactWidthRegularHeight;// return YES for an iPhone in portrait

 

@end

Objective C .m file

#import "UIViewController+BWAdditions.h"
 


@implementation UIViewController (BWAdditions)

 

- (BOOL)isPortrait { CGRect orientationRect = [[UIScreen mainScreen] bounds]; return (orientationRect.size.height > orientationRect.size.width) ? YES : NO; }

 

- (BOOL)isSizeClassesBothRegular { return (self.traitCollection.verticalSizeClass == UIUserInterfaceSizeClassRegular && self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassRegular) ? YES : NO; }

 

- (BOOL)isSizeClassesCompactWidthRegularHeight { return (self.traitCollection.verticalSizeClass == UIUserInterfaceSizeClassRegular && self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact) ? YES : NO; }

 

@end