更改 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()
}
}
}
我 运行 遇到一个问题,在我的 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()
}
}
}