UITraitCollection Clarification
This document (scroll to Unified Storyboards for Universal Apps) explains the size classes for both iPads and iPhones.
Note that the iPhone is a bit tricky. All iPads are Regular-x-Regular in any orientation, but an iPhone's size classes change on orientation, from Regular(h)-x-Compact(w) in Portrait, to Compact-x-Compact in Landscape.
The rumored explanation for all these changes is that Apple might be introducing more screen resolutions soon, and the current number already requires a bunch of if-then's without these size classes. To ease this transition, I'd recommend thinking about things more like responsive web design, where you define a few general layouts, then stretch things to fit nicely at any exact size within one of those layouts.
EDIT:
1) In case the link breaks, find the "Whats New in iOS" Apple Doc, go to the iOS8 section, and look for "Supporting New Screen Sizes and Scales"
2) The iPhone 6+ has a regular width in landscape mode.
UITraitCollection iPad how to detect the current orientation
Using -orientation
property of UIDevice is not correct (even if it could work in most of cases) and could lead to some bugs, for instance UIDeviceOrientation
consider also the orientation of the device if it is face up or down, there is no pair in UIInterfaceOrientation
enum for those values.
Furthermore, if you lock your app in some particular orientation, UIDevice will give you the device orientation without taking that into account.
On the other side iOS8 has deprecated the interfaceOrientation
property on UIViewController
class.
There are 2 options available to detect the interface orientation:
- Use the status bar orientation
- Use size classes, on iPhone if they are not overridden they could give you a way to understand the current interface orientation
What is still missing is a way to understand the direction of a change of interface orientation, that is very important during animations.
In the session of WWDC 2014 "View controller advancement in iOS8" the speaker provides a solution to that problem too, using the method that replaces -will/DidRotateToInterfaceOrientation
.
Here the proposed solution partially implemented:
-(void) viewWillTransitionToSize:(CGSize)s withTransitionCoordinator:(UIVCTC)t {
orientation = [self orientationFromTransform: [t targetTransform]];
oldOrientation = [[UIApplication sharedApplication] statusBarOrientation];
[self myWillRotateToInterfaceOrientation:orientation duration: duration];
[t animateAlongsideTransition:^(id <UIVCTCContext>) {
[self myWillAnimateRotationToInterfaceOrientation:orientation
duration:duration];
}
completion: ^(id <UIVCTCContext>) {
[self myDidAnimateFromInterfaceOrientation:oldOrientation];
}];
}
How to create UITraitCollection with both size classes in code?
Ok, I have found solution:
let compactTraitCollection = UITraitCollection(traitsFromCollections: [UITraitCollection(verticalSizeClass: .Compact), UITraitCollection(horizontalSizeClass: .Compact)])
XCTAssertFalse(compactTraitCollection.isIpad)
let regularTraitCollection = UITraitCollection(traitsFromCollections: [UITraitCollection(verticalSizeClass: .Regular), UITraitCollection(horizontalSizeClass: .Regular)])
XCTAssertTrue(regularTraitCollection.isIpad)
Swift: If traitCollection.userInterfaceStyle == .unspecified, how do I determine if it's in light or dark mode?
You can use UIScreen.main.traitCollection.userInterfaceStyle
to get the current device theme independent of the overridden appearance on the window.
iOS- Detect current size classes on viewDidLoad
As of iOS 8 UIViewController adopts the UITraitEnvironment protocol. This protocol declares a property named traitCollection which is of type UITraitCollection. You can therefor access the traitCollection property simply by using self.traitCollection
UITraitCollection has two properties that you want to access named horizontalSizeClass and verticalSizeClass Accessing these properties return an NSInteger. The enum that defines the returned values is declared in official documentation as follows- (this could potentially be added to in the future!)
typedef NS_ENUM (NSInteger, UIUserInterfaceSizeClass {
UIUserInterfaceSizeClassUnspecified = 0,
UIUserInterfaceSizeClassCompact = 1,
UIUserInterfaceSizeClassRegular = 2,
};
So you could get the class and use say a switch to determine your code direction. An example could be -
NSInteger horizontalClass = self.traitCollection.horizontalSizeClass;
NSInteger verticalCass = self.traitCollection.verticalSizeClass;
switch (horizontalClass) {
case UIUserInterfaceSizeClassCompact :
// horizontal is compact class.. do stuff...
break;
case UIUserInterfaceSizeClassRegular :
// horizontal is regular class.. do stuff...
break;
default :
// horizontal is unknown..
break;
}
// continue similarly for verticalClass etc.
Related Topics
How to Update Particular Value of Child in Firebase Db
Swift: Terminating with Uncaught Exception of Type Nsexception
How to Read References Given by Ptr_Refs in iOS
Vnfaceobservation Boundingbox Not Scaling in Portrait Mode
Is Weak Self Needed for Table View Cell Button Closure
Delegate Seems to Not Be Working, According to the Console
Save Uiimage Array in Nsuserdefaults
Admob Interstitial Alway Returns False
Delete Image from Photo Gallery
Get Light or Dark Variant of a Color Declared in Assets
iOS Swift Avplayer Inside Uiview How to Make It Work
Swiftui Card Flip Animation with Two Views, One of Which Is Embedded Within a Stack
Format String with Variadic Arguments
Wkwebview: How to Preload Multiple Urls
Viewcontroller.Type Does Not Have a Member Names 'Answerone' - Swift