以前,他们制作了单独的xib来支持iPad。 为了统一布局,Apple在2014年推出了Auto Layout和Size Classs ,以及自适应导航UISplitViewController 。

拆分控制器是一个容器,将两个控制器并排放置。 在左侧,将有一个导航控制器(与导航控制器无关),在右侧,对应于导航中的选择。 简而言之,与“设置”中的一样。
让我们UISplitViewController
如何在屏幕上配置UISplitViewController
及其行为。
定义控制器
表示左侧(导航)和右侧控制器。 两者都设置标题:
class MasterController: UITableViewController { override func viewDidLoad() { super.viewDidLoad() self.navigationItem.title = "Master" self.navigationController?.navigationBar.prefersLargeTitles = true } } class DetailController: UIViewController { override func viewDidLoad() { super.viewDidLoad() self.navigationItem.title = "Detail" self.navigationController?.navigationBar.prefersLargeTitles = true } }
拆分控制器是两个控制器的容器。 正如我在kat之前写的那样,左侧是导航主控制器,右侧是对应于导航中的选项或详细信息(详细信息控制器)。 记住“大师”和“细节”,这些词会在文档和协议中找到。
添加拆分
让我们转到AppDelegate,在didFinishLaunchingWithOptions方法中创建一个新窗口,初始化Split控制器和另外两个,将其设置为Split:
let masterController = MasterController() let masterNavigationController = UINavigationController(rootViewController: masterController) let detailController = DetailController() let detailNavigationController = UINavigationController(rootViewController: detailController) let splitViewController = UISplitViewController() splitViewController.viewControllers = [masterNavigationController, detailNavigationController] self.window = UIWindow(frame: UIScreen.main.bounds) self.window!.rootViewController = splitViewController self.window!.makeKeyAndVisible()
运行模拟器。 纵向和横向方向分别为:

在端口方向上,主控制器不可见。 向左滑动即可显示。 它是使用模式配置的,我们将进一步分析它们。
导览
将单元格添加到主控制器。 让我提醒您,主控制器是包装在UINavigationController中的表。
您知道如何添加单元格,无需查看代码 class MasterController: UITableViewController { override func viewDidLoad() { self.tableView = UITableView(frame: .zero, style: .insetGrouped) super.viewDidLoad() self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "id") self.navigationItem.title = "Master" self.navigationController?.navigationBar.prefersLargeTitles = true } override func numberOfSections(in tableView: UITableView) -> Int { return 2 } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 4 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "id")! cell.textLabel?.text = "\(indexPath)" return cell } }
如果您不知道如何操作,请点击这里 。
在iOS 13中, 出现了新的.insetGrouped表样式,我安装了它。 该样式从Xcode 11开始可用。
运行项目:

通过单击该单元格,我们将显示一个详细的控制器。 “详细控制器”如何减少谣言,我希望在评论中能更好地告诉我翻译。 代码如下:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let controller = DetailController() controller.navigationTitle = "\(indexPath)" self.showDetailViewController(UINavigationController(rootViewController: controller), sender: nil) }
还记得命名主控制器/详细控制器吗? 这是在showDetailViewController方法中使用Detail的示例。
细心的人会注意到控制器没有navigationTitle 。 更新Detail控制器的类:
class DetailController: UIViewController { var navigationTitle: String = "Detail" override func viewDidLoad() { super.viewDidLoad() self.navigationItem.title = navigationTitle self.view.backgroundColor = .white } }
运行项目,然后单击单元格:

iPhone手机
导航是自适应的,这意味着一切就绪。 好吧,差不多。 选择一个iPhone并运行:

像常规导航控制器一样工作。 是 普遍性 适应性-根据可用空间,拆分控制器放置主控制器和详细控制器。
不是Master控制器,但Detail是第一个在iPhone上打开的控制器。 UISplitViewControllerDelegate委托配置了从显示两个控制器到一个类似情况的过渡 。 返回值确定是显示“主控制器”还是“详细信息”:
extension AppDelegate: UISplitViewControllerDelegate { func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController: UIViewController, onto primaryViewController: UIViewController) -> Bool { return true } }
此方法并不总是必须返回true。 示例:将方向更改为紧凑型且已打开的“细节”控制器时,可能需要在屏幕上保留“细节”。 计划此行为。

iPhone版风景
iPhone的横向模式默认情况下不使用拆分。 这已通过“拆分”控制器的显示模式进行了纠正:
splitViewController.preferredDisplayMode = UISplitViewController.DisplayMode.allVisible
我们设置了首选的显示模式,即在可能的情况下显示“主/从”对。 该能力决定了API,无法进行配置。
在纵向方向上将保持不变。 但是在风景中(仅适用于Xs Max和8+):
如果SDK中Split控制器的条件发生变化,则您的项目将默认实现它们。
尺寸图
可定做。 这是通过长宽比完成的:
splitViewController.preferredPrimaryColumnWidthFraction = 0.5 splitViewController.maximumPrimaryColumnWidth = 2000
母版和明细将具有相同的大小。 确保设置maximumPrimaryColumnWidth 。 (可选)您可以设置最小宽度。 我不会添加屏幕截图,该教程的ipad太多了)
隐藏大师
添加一个按钮以全屏方式打开“细节”。 拆分控制器必须处于.allVisible模式。 将Detail控制器的代码粘贴到viewDidLoad中 :
if let splitController = self.splitViewController{ if let navController = splitController.viewControllers.last as? UINavigationController { navController.topViewController?.navigationItem.leftBarButtonItem = splitController.displayModeButtonItem } }
很难描述这种行为,而gif就是莫斯科预算的大小。 因此截图:

或者我在Twitter上有一个视频。
指导方针
AutoLayout放置元素后,Split控制器确定导航。 苹果强烈建议使用静态主控制器 。 为了进行实验,我在左侧推了一个导航控制器,方法是单击推入控制器的单元格(而不是更新Detail控制器)。 看起来很奇怪。
通常,将导航限制为拆分视图的一侧。 将导航放置在拆分视图的两个窗格中会使人们难以保持方向并辨别两个窗格之间的关系。
突出显示主控制器中的活动选择。 尽管“细节”控制器的内容可能有所不同,但它应始终与“主控”上的选择匹配。 这将帮助人们控制控制器之间的关系。 控制控制器-一种双关语。
无需到处使用Split。 但是,如果您的应用程序具有强大的导航功能,并且根控制器是“ Tab”或“导航”,则“拆分”很有用。 如果您具有单屏幕翻译器应用程序,则不需要拆分。
对于寻求者
链接到文档 ,链接到指南 。
如果您喜欢观看视频,请查看教程: