Showing/Hiding UISplitViewController 的主视图控制器转换详细视图

Showing/Hiding primary view controller of UISplitViewController shifts detail view

我在 iPad 上有一个用于 Master/Detail 功能的 UISplitViewController。主视图控制器显示项目列表,当用户选择一个项目时,详细信息显示在详细视图控制器中。我将详细视图控制器设置为导航到另一个视图控制器以显示图形。发生这种情况时,我会在 prepareForSeque 中使用以下行隐藏主视图控制器。

if let svc = self.splitViewController {
    svc.preferredDisplayMode = .PrimaryHidden
}

效果很好。从图形视图导航回详细视图时,我想再次显示拆分视图控制器的主视图。我把它放在 viewWillAppear 中。

guard let svc = self.splitViewController else { return }

if svc.preferredDisplayMode != .Automatic {
    svc.preferredDisplayMode = .Automatic
}

再次,这完全符合我的预期。问题是详细视图在此过程中更改了大小,并且从图形视图返回时布局不正确。

这是导航到图形视图之前以及隐藏 UISplitViewController 的主视图之前的屏幕截图。

这是从图形视图返回后的情况。

我试图解决这个问题是强制详细视图自行布局。我尝试了以下方法:

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()

    guard let svc = self.splitViewController else { return }
    let detailNavController = svc.viewControllers[svc.viewControllers.count-1] as! UINavigationController
    detailNavController.view.setNeedsLayout()
}

它有点管用,但会导致界面出现丑陋的跳转,因为详细视图会出现,然后在一秒钟后重新布局。有没有更好的方法让视图在显示之前正确布局?

我让它工作了,我想我会分享以防其他人遇到同样的问题。正如蒂姆在评论中所说,这是一个 运行 在链中足够早的布局问题,以便在视图显示在屏幕上之前进行布局。

我在图形视图控制器场景中做了以下操作:

override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)
    guard let svc = self.splitViewController else { return }
    svc.preferredDisplayMode = .Automatic
}

这会将拆分视图重新设置为在此过程的早期同时显示主视图控制器和辅助视图控制器。

我出错的地方是我的详细视图控制器的父级是 UINavigationController。我假设因为它的大小错误,我需要在设置拆分视图控制器以显示主视图和次视图后让它重新布局。这是一个错误的假设。最终起作用的是上升到 UISplitviewController 的一个层次,并让它自己执行布局。

在我的详细视图控制器中,我执行了以下操作:

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    guard let svc = self.splitViewController else { return }
    svc.view.setNeedsLayout()
    svc.view.layoutIfNeeded()
}

这在链中足够早,所有布局都在视图显示之前完成,但足够晚,拆分视图控制器具有适当的大小信息来显示主视图和辅助视图。

希望这对其他人有所帮助,并感谢您的评论。