iPhone 和 iPad 设备之间的 UIWindow 方向不一致?

UIWindow orientation inconsistent between iPhone and iPad devices?

我正在尝试为覆盖行为创建自定义 UIWindow,而且我到处都看到 "UIWindow is not orientation based"; 正是我想要的,因为我想匹配物理设备的边框。

在 iPhone 上,一切正常,UIWindow 保持一致,并且我有一个很好的和静止的行为;旋转设备时边框不会移动:

在 iPad 上,使用完全相同的代码,我在 UIWindow 层上获得了一个旋转动画(我用来绘制边框), 它使这个奇怪的布局发生:

我不使用轮换通知;因为我不想回应轮换。我使用 UIScreen nativeBounds "non-oriented aware" 边界来确保我没有方向敏感的东西。这种跨设备的不同行为让我很不舒服。

是否有人已经 运行 陷入那种奇怪的行为?你如何回应它? 有好的做法或解决方法吗?

项目的完整代码,包括示例应用程序在这里: https://github.com/Dean151/RecordingOverlay

overlay和UIWindow子类的具体代码在这里: https://github.com/Dean151/RecordingOverlay/blob/master/Sources/RecordingOverlay/RecordingOverlay.swift

事实证明,如果满足某些条件,windows 会自动旋转。当满足所有这些参数时,我不得不覆盖旋转。

如果所有这些都成立,UIWindow 将自动旋转:

  • iOS 至少为 9.0
  • 设备是 iPad
  • 应用程序支持所有设备旋转
  • 应用程序使用故事板作为其主界面(在 info.plist 中声明)
  • 应用程序不需要全屏(在 info.plist 中声明)

您可以使用一个小片段检测到:

@available(iOS 9.0, *)
var willAutorotate: Bool {
    guard UIDevice.current.userInterfaceIdiom == .pad else {
      return false
    }

    let window = UIApplication.shared.delegate?.window ?? nil
    guard UIApplication.shared.supportedInterfaceOrientations(for: window) == .all else {
        return false
    }

    let info = Bundle.main.infoDictionary ?? [:]
    guard info["UIRequiresFullScreen"] as? Bool != true else {
        return false
    }

    guard info["UILaunchStoryboardName"] != nil else {
        return false
    }

    return true
}

现在我知道它何时会自动旋转,我可以将框架和变换更改为 "cancel" 旋转。