为什么我不能在第一个 运行 的 UISplitViewController 中将 Master 和 Detail 视图并排放置,但在旋转时它可以工作?

Why can I not place Master and Detail view next to each other in UISplitViewController on the first run, but upon rotation it works?

我有一个拆分视图控制器,左侧是项目列表,右侧是详细视图。 AppDelegate中的相关代码:

let splitViewController = mainView.instantiateViewControllerWithIdentifier("initial") as! UISplitViewController



        let rightNavController = splitViewController.viewControllers.last as! UINavigationController
        let detailViewController = rightNavController.topViewController as! DetailsIpad

        let leftNavController = splitViewController.viewControllers.first as! UINavigationController
        let masterViewController = leftNavController.topViewController as! MainViewController

        masterSplitViewController = masterViewController
        detailSplitViewController = detailViewController

        // Override point for customization after application launch.
        let navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as! UINavigationController
        navigationController.topViewController!.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem()
        splitViewController.delegate = self

        self.window!.rootViewController = splitViewController

当我第一次启动应用程序时,我看到分屏的右侧部分占据了整个屏幕:

如果我旋转屏幕,它就会正确设置(可能是因为两个视图都出现在屏幕上):

当我在各处设置断点时,我看到右侧的详细视图在左侧的主视图(项目列表)之前加载,尽管没有被直接调用。 我无法更改调用分屏视图的顺序。我该如何解决这个问题?

更新:

我可以在显示拆分视图控制器之前进行设置:

splitViewController.preferredDisplayMode = UISplitViewControllerDisplayMode.AllVisible

并且在我打印时在拆分控制器的 ViewDidLoad 中:

print(self.preferredDisplayMode.rawValue)

我得到:2,这是 AllVisible。但是结果还是一样。

这是 UISplitViewController 的默认行为。仔细看看下面-

// An animatable property that controls how the primary view controller is hidden and displayed. A value of `UISplitViewControllerDisplayModeAutomatic` specifies the default behavior split view controller, which on an iPad, corresponds to an overlay mode in portrait and a side-by-side mode in landscape.
@property (nonatomic) UISplitViewControllerDisplayMode preferredDisplayMode NS_AVAILABLE_IOS(8_0);

这是相同定义的关键部分-

on an iPad, corresponds to an overlay mode in portrait and a side-by-side mode in landscape.

另外,如果你想查询一个UISplitViewController的当前状态(显示模式)你应该使用这个属性-

// The actual current displayMode of the split view controller. This will never return `UISplitViewControllerDisplayModeAutomatic`.
@property (nonatomic, readonly) UISplitViewControllerDisplayMode displayMode NS_AVAILABLE_IOS(8_0);

请记住,您不能将其与 UISplitViewControllerDisplayModeAutomatic 进行比较,因为-

This will never return UISplitViewControllerDisplayModeAutomatic.

我的建议是将 preferredDisplayMode 设置为您想要的值。在您的情况下,您似乎需要 primary (master) 始终可见。所以这是建议的解决方案-

mySplitVC.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible

为什么它首先加载辅助(细节)控制器?

如您所见,UISplitViewController 实例无论 displayMode 当前处于什么状态,总是需要详细视图。所以这是一个很好的电话

  • 首先加载详细视图。
  • 之后加载主视图(有条件地基于 displayMode)。

希望对您有所帮助。

感谢@Tarun Tyagi 的解释,但就我而言,建议的操作无效。但是,这对我有用:在 SplitViewController 中,我添加了对 setNeedsLayout():

的调用
override func viewDidAppear(animated: Bool) {
    self.view.setNeedsLayout()
}

当视图已经显示在屏幕上时,这将使视图刷新。