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

时间:2015-02-15 17:40:04

标签: ios objective-c iphone iphone-6-plus

在我的通用应用程序中,我当前在窗口的根视图控制器中覆盖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之前进行运行时检查。

4 个答案:

答案 0 :(得分:2)

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

#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) { ... }

答案 1 :(得分:1)

缺乏正式的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;
  }
}

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

虽然这个解决方案相当简单,但我完全喜欢,因为缺乏复杂性。我并不需要准确区分设备,所以任何聪明的解决方案(例如Jef's answer中的解决方案对我来说都是过度的。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

Fwiw,相当于Swift 1.2中的herzbube's answer

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