更改 Nav 的 rootViewController 会导致 UISplitViewController 在 Compact portrait orientation 上显示详细信息

Changing rootViewController for Nav causes UISplitViewController to show detail on Compact portrait orientation

我 运行 遇到一个问题,在我的 UINavigationController 上更改 rootViewController 并将其改回原来的 UINavigationController 后,UISplitViewController 开始在 phone 设备中以 compact/portrait 方向显示它的主视图和细节视图(因此不仅在大尺寸 phones 上,还有其他尺寸)。

架构的基本概述: TabBarController 包含多个选项卡。这些选项卡之一是 UISplitViewController。我目前覆盖以下内容以确保 MasterViewController 显示在紧凑的方向上:

func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController: UIViewController, onto primaryViewController: UIViewController) -> Bool {

    // this prevents phone from going straight to detail on showing the split view controller
    return true
}

这工作正常,并按预期以纵向显示母版。在任何时候按下另一个选项卡上的按钮都可以创建一个新的 UINavigationController 实例并显示它,我正在执行以下操作将 rootViewController 更改为新创建的 UINavigationController 以显示:

let appDelegate = UIApplication.shared.delegate
appDelegate?.window??.rootViewController = newNavVC

关闭时,我只是通过上面的相同代码将 UINavigationController 换回原来的那个。但是,一旦我这样做了一次(创建 nav/display/dismiss),然后我将选项卡切换回带有 UISplitViewController 的选项卡,它就会自行更改以显示并排的主详细信息视图。我不知道这在纵向模式下可以实现紧凑的尺寸。我尝试更改为 UISplitViewController 中 4 种首选显示模式中的任何一种,但这并没有解决问题。

下面是它的样子(iPhone 6模拟器),我是漏代表还是误会崩溃了?

之前:

之后:

您可以将分配 rootViewController 的逻辑替换为在此 link:

中找到的代码片段

Leaking views when changing rootViewController inside transitionWithView

基本上您只需为 UIWindow 创建一个扩展 class 即可正确设置根视图控制器。

extension UIWindow {

/// Fix for 
func set(rootViewController newRootViewController: UIViewController, withTransition transition: CATransition? = nil) {

    let previousViewController = rootViewController

    if let transition = transition {
        // Add the transition
        layer.add(transition, forKey: kCATransition)
    }

    rootViewController = newRootViewController

    // Update status bar appearance using the new view controllers appearance - animate if needed
    if UIView.areAnimationsEnabled {
        UIView.animate(withDuration: CATransaction.animationDuration()) {
            newRootViewController.setNeedsStatusBarAppearanceUpdate()
        }
    } else {
        newRootViewController.setNeedsStatusBarAppearanceUpdate()
    }

    /// The presenting view controllers view doesn't get removed from the window as its currently transistioning and presenting a view controller
    if let transitionViewClass = NSClassFromString("UITransitionView") {
        for subview in subviews where subview.isKind(of: transitionViewClass) {
            subview.removeFromSuperview()
        }
    }
    if let previousViewController = previousViewController {
        // Allow the view controller to be deallocated
        previousViewController.dismiss(animated: false) {
            // Remove the root view in case its still showing
            previousViewController.view.removeFromSuperview()
        }
    }
}