Allow landscape for iPhone 6 Plus but not other iPhone

In my generic application, I am currently redefining supportedInterfaceOrientations in the window's root window controller to determine the allowed orientations. So far, the solution has been based on the idiom of the device user interface:

 - (NSUInteger) supportedInterfaceOrientations { if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) return (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown); else return UIInterfaceOrientationMaskAll; } 

Now I would like to change this so that I can also support the landscape for the iPhone 6 Plus, but NOT for other iPhones. I can create one or two solutions, but all of them are quite fragile and are likely to break when Apple starts creating new devices.

In an ideal world, I would like to modify the above method to look like the following snippet, in which the solution is based on the device user interface size class, and not on the user interface idiom:

 - (NSUInteger) supportedInterfaceOrientations { // Note the hypothetical UIDevice method "landscapeSizeClass" if ([[UIDevice currentDevice] landscapeSizeClass] == UIUserInterfaceSizeClassCompact) return (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown); else return UIInterfaceOrientationMaskAll; } 

Is there something like this magic landscapeSizeClass method somewhere in UIKit? I looked around a bit in various reference books and class manuals, but did not find anything useful. Or can someone suggest another solution that will be similarly universal and promising?

Please note that my application creates a programmatic interface, so there is no reason for a storyboard based solution. Also, my application still needs iOS 7 support, so I can't just change everything to use size classes. However, I can do performance checks before using the simple iOS 8 APIs.

+5
source share
4 answers

The lack of an official Apple API is the workaround I came up with:

 - (NSUInteger) supportedInterfaceOrientations { if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { // iPhone 5S and below: 320x480 // iPhone 6: 375x667 // iPhone 6 Plus: 414x736 CGSize screenSize = [UIScreen mainScreen].bounds.size; // The way how UIScreen reports its bounds has changed in iOS 8. // Using MIN() and MAX() makes this code work for all iOS versions. CGFloat smallerDimension = MIN(screenSize.width, screenSize.height); CGFloat largerDimension = MAX(screenSize.width, screenSize.height); if (smallerDimension >= 400 && largerDimension >= 700) return UIInterfaceOrientationMaskAll; else return (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown); } else { // Don't need to examine screen dimensions on iPad return UIInterfaceOrientationMaskAll; } } 

The fragment simply assumes that a screen with sizes above a semi-randomly selected size is suitable for rotation. Semi-random, because the 400x700 threshold includes the iPhone 6 Plus, but excludes the iPhone 6.

Although this solution is quite simple, I like it precisely because of its lack. I don’t need to clearly distinguish between devices, so any smart solutions, such as the answer in the Jef answer , are redundant for my purposes.

+1
source

I would rather use macros to detect this (for readability), with something like:

 #define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) #define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) #define SCREEN_WIDTH ([[UIScreen mainScreen] bounds].size.width) #define SCREEN_HEIGHT ([[UIScreen mainScreen] bounds].size.height) #define SCREEN_MAX_LENGTH (MAX(SCREEN_WIDTH, SCREEN_HEIGHT)) #define SCREEN_MIN_LENGTH (MIN(SCREEN_WIDTH, SCREEN_HEIGHT)) #define IS_IPHONE_6P (IS_IPHONE && SCREEN_MAX_LENGTH == 736.0) 

And then:

  - (NSUInteger) supportedInterfaceOrientations { if (IS_IPAD || IS_IPHONE_6P) { return UIInterfaceOrientationMaskAll; } else { return (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown); } } 

Edited by:

It is better to have this one macro instead of IS_IPHONE_6P and IS_IPAD:

 #define IS_LANDSCAPE_REGULAR_SIZE (SCREEN_MAX_LENGTH >= 736.0) 

And then:

 if (IS_LANDSCAPE_REGULAR_SIZE) { ... } 
+1
source
 - (NSUInteger) supportedInterfaceOrientations { if (self.traitCollection.verticalSizeClass == UIUserInterfaceSizeClassRegular || self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassRegular) { return UIInterfaceOrientationMaskAll; } else { return (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown); } } 

Update: The previous one does not work, so this is another solution.

 - (NSUInteger) supportedInterfaceOrientations { if (self.traitCollection.displayScale == 3.0 || (self.traitCollection.verticalSizeClass == UIUserInterfaceSizeClassRegular && self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassRegular)) { return UIInterfaceOrientationMaskAll; } else { return (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown); } } 
0
source

Fwiw, equivalent to herzbube answer in Swift 1.2:

 override func supportedInterfaceOrientations() -> Int { if UIDevice.currentDevice().userInterfaceIdiom == .Phone { let size = self.view.bounds.size let smallerDimension = min(size.width, size.height) let largerDimension = max(size.width, size.height) if smallerDimension >= 400 && largerDimension >= 700 { return Int(UIInterfaceOrientationMask.All.rawValue) } else { return Int(UIInterfaceOrientationMask.Portrait.rawValue) } } else { return Int(UIInterfaceOrientationMask.All.rawValue) } } 

although I personally prefer the following style:

 override func supportedInterfaceOrientations() -> Int { if UIDevice.currentDevice().userInterfaceIdiom == .Pad { return Int(UIInterfaceOrientationMask.All.rawValue) } let size = self.view.bounds.size let smallerDimension = min(size.width, size.height) let largerDimension = max(size.width, size.height) return smallerDimension >= 400 && largerDimension >= 700 ? Int(UIInterfaceOrientationMask.All.rawValue) : Int(UIInterfaceOrientationMask.Portrait.rawValue) } 
0
source

All Articles