对 iPhone 6 次以上的旋转做出反应——traitCollectionDidChange:为导航控制器调用了两次

React to iPhone 6+ rotation -- traitCollectionDidChange: called twice for nav controller

我用UISplitViewController。当用户将他的 iPhone 6 Plus 旋转成纵向并且不再看到任何细节时,我想显示一个空的选择细节场景。 (所有其他设备的行为都可以预见。只有 6 Plus 可以更改其外观。)我现在使用 split view delegate 来代替它,这涉及到一些奇怪的查询,但这不是重点。

我想知道如何确定 iPhone 6 是否旋转到横向。

我想到的最好的主意:对特征环境变化做出反应。主视图控制器始终保持紧凑,只有它的父导航视图控制器从紧凑变为常规,然后再变回来。 (当然还有 UIWindow。)

当使用拆分视图控制器时,对于 "Master" 中 UINavigationController 的子类,traitCollectionDidChange: 将在使用 iPhone 6 Plus 并旋转到景观。回转时调用一次

willTransitionToTraitCollection:withTransitionCoordinator:分别被调用了3次和1次

我想那是因为在风景中你可以看到两个并排的视图控制器。不过,UINavigationController 根本没有收到对子视图控制器的调用,这对我来说没有意义。

由于 UITraitCollections 不包含有关哪个视图控制器受到影响的信息,我无法确定环境是否从常规大小可靠地更改为紧凑的水平大小。其中一个特征集合将报告正确的新值,但我无法将它们彼此区分开来。

既然使用不同的值多次调用回调,您是如何解决这个问题的?

我知道这是一个旧线程,但我无法在网上找到相同问题的解决方案,所以这是我的两分钱。

UISplitViewController 是一个容器视图控制器。所以它被认为是 "displayed" 即使它上面有视图控制器。在苹果文档中它说:

"View controllers forward the trait change message to their child view controllers. Presentation controllers forward the trait change to their presented view controller."

因此,每当您更改拆分视图控制器的大小 class 时,它都会调用它的委托及其两个子项的委托。

更多信息请查看:https://developer.apple.com/reference/uikit/uicontentcontainer/1621511-willtransitiontotraitcollection

编辑:我刚刚注意到我没有完全解释为什么 UISplitViewController 被调用三次。如果 willTransitionToTraitCollection:withTransitionCoordinator: 未在呈现的视图中实现,它可能遵循 Apple 为其设置的约定:

"If you override this method in your own objects, always call super at some point in your implementation so that UIKit can forward the trait changes to the associated presentation controller and to any child view controllers."

我认为它背后的想法是,在子视图控制器的 traitCollection 发生变化时,您可能想要更改布局 and/or 其兄弟姐妹的数量。为此,子控制器中的任何更改都必须调用容器,以便它知道发生了什么并相应地进行调整。但是,它无法跟踪哪些更改与其他更改重叠,因此所有更改都会被注册。

我的解决方案是处理子视图控制器(在我的例子中是 UINavigationControllers)而不是 splitViewController 的变化,方法是通过子视图控制器 class 处理它们并添加转换逻辑。