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