为啥我不能在第一次运行时在 UISplitViewController 中将 Master 和 Detail 视图彼此相邻放置,但在旋转时它可以工作?

Posted

技术标签:

【中文标题】为啥我不能在第一次运行时在 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?为什么我不能在第一次运行时在 UISplitViewController 中将 Master 和 Detail 视图彼此相邻放置,但在旋转时它可以工作? 【发布时间】:2016-06-09 13:51:55 【问题描述】:

我有一个拆分视图控制器,左侧是项目列表,右侧是详细视图。 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。但结果还是一样。

【问题讨论】:

我不确定问题是视图加载的顺序。这是横向/纵向模式下 splitView 控制器的默认行为。您是否希望在纵向模式下,详细视图位于主视图旁边? @DJohnson 实际上,对不起,不,只有在横向模式下我希望它是这样的(纵向模式未激活) 您在加载第二个视图后尝试-setNeedsUpdateConstraints 吗? 是的,我也试过这个..没用 你试过按数组设置视图控制器吗?喜欢splitViewController.viewControllers = [master, detail] 【参考方案1】:

这是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);

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

在 iPad 上,对应于纵向的叠加模式和横向的并排模式。

另外,如果你想查询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 进行比较,因为-

这永远不会返回UISplitViewControllerDisplayModeAutomatic

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

mySplitVC.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible

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

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

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

希望这会有所帮助。

【讨论】:

这是问题所在:我已经在 self.preferredDisplayMode = UISplitViewControllerDisplayMode.AllVisible 上设置了此设置,并尝试了所有其他方法 - 对我没有帮助 我被排除在外,只有唯一的选择:从头开始重新完成整个教程,因为似乎没有任何效果【参考方案2】:

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

override func viewDidAppear(animated: Bool) 
    self.view.setNeedsLayout()

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

【讨论】:

以上是关于为啥我不能在第一次运行时在 UISplitViewController 中将 Master 和 Detail 视图彼此相邻放置,但在旋转时它可以工作?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在我第一次单击按钮时在我的 RecyclerView 中调用绑定?

为啥我在运行 Python 时在 Spyder 中收到“启动内核时发生错误”?

为啥我在第二次运行测试时在 Mongoose 中收到错误“一旦编译后无法覆盖模型”?

为啥我在第二次运行测试时在 Mongoose 中收到错误“一旦编译后无法覆盖模型”?

为啥我在安装sql2005时在解决那个com功能警告时在dos时为啥显示msdtc不是内部命令啊 怎么解决?

从 tableview 中选择时在多个详细视图之间切换