允许iPhone 6 Plus的横向,但不允许其他iPhone

在我的通用应用程序中,我当前覆盖窗口根视图控制器中的supportedInterfaceOrientations ,以定义允许的方向。 到目前为止,决定是基于设备的用户界面习语:

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

现在我想改变它,以便我也可以支持iPhone 6 Plus的风景,但不支持其他iPhone。 我可以想象一两个解决方案,但这些都非常脆弱,并且可能会在Apple开始制造新设备时中断。

在理想的世界中,我想将上述方法更改为以下代码段,其中决策基于设备的用户界面大小类而不是用户界面惯用法:

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

在UIKit的某个地方有类似神奇的landscapeSizeClass方法吗? 我在各种课程参考和指南中看了一下,但没有找到任何有用的东西。 或者有人可以建议一个同样通用且面向未来的不同解决方案吗?

请注意,我的应用程序以编程方式创建其UI,因此纯粹基于故事板的解决方案已经完成。 此外,我的应用程序仍然需要支持iOS 7,所以我不能只是改变一切使用大小类。 但是,我可以做的是在使用简单的iOS 8 API之前进行运行时检查。

我宁愿使用宏来发现(出于可读性的原因),例如:

 #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) 

接着:

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

编辑:

最好有一个宏而不是IS_IPHONE_6P和IS_IPAD:

 #define IS_LANDSCAPE_REGULAR_SIZE (SCREEN_MAX_LENGTH >= 736.0) 

接着:

 if (IS_LANDSCAPE_REGULAR_SIZE) { ... } 

缺乏正式的Apple API,这是我提出的解决方法:

 - (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; } } 

该片段简单地假设尺寸高于半任意选择尺寸的屏幕适合于旋转。 随意,因为400×700的门槛包括iPhone 6 Plus,但不包括iPhone 6。

虽然这个解决方案相当简单,但我完全喜欢它, 因为它缺乏复杂性。 我真的不需要区分设备,所以任何聪明的解决方案,例如杰夫答案中的解决方案,对我来说都是过度的。

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

更新:以前不工作所以这里是不同的解决方案

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

Fwiw,相当于herzbube在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) } } 

虽然我个人更喜欢以下风格:

 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) }