修复UISplitView的顽固大标题

我发现UISplitViewController出现了一个与iOS 11的新大标题有关的烦人的bug:当UISplitView折叠时,当用户滚动详细视图控制器时,大标题拒绝缩小和拉伸。

该错误仅在详细视图控制器上显示,并且仅在拆分视图折叠(紧凑宽度)时显示。 本文介绍了该错误的原因以及解决该错误的两种解决方案。 在Xcode 9.2 / iOS 11.3上发现了错误。

UINavigationController向下搜索当前子级的视图层次结构以搜索UIScrollView。 请记住,UITableView和UICollectionView也是UIScrollViews。 首先,UINavigationController查看子级的基本视图,然后检查基本视图内的第一个视图。 之后,它放弃寻找! 如果找到滚动视图,则导航栏将挂接到滚动事件,并根据用户滚动自动调整大标题和栏的大小。 这一切都很好,当用户上下滚动时,标题将缩小和拉伸。 但是,如果导航栏找不到滚动视图怎么办? 运气不好,它不会收缩或伸展。 这里的漏洞在于拆分视图折叠了,只是在详细视图控制器中找不到滚动视图。 但是为什么找不到滚动视图? 让我们更深入…

UISplitView会根据其大小类自动进行调整。 当它的宽度变紧凑时,它会自动折叠成一个简单的UINavigationController。 但是如何? 引擎盖下面发生了什么?

拆分视图适应后,只需将详细信息视图推送到主视图的UINavigationController上。 但这是棘手的部分: 典型的拆分视图设置包含两个UINavigationControllers。 Master具有其自己的UINavigationController,而Detail具有完全不同的UINavigationController。 拆分视图折叠后,Detail的UINavigationController会发生什么? 让我们拉起Xcode的漂亮视图层次调试器并找出答案。

调试器显示两个UINavigationControllers:嵌套在Master的导航控制器内部的Detail的导航控制器。 那么Master的导航控制器如何向下搜索并找到UIScrollView? 请记住,它需要找到此滚动视图才能缩小大标题。 答案:找不到它! 这就是为什么它不起作用。 嵌套在其中的第二个UINavigationController会掩盖搜索。 这就是大标题拒绝缩小和拉伸的原因。 至少那是我的有根据的猜测。

一个简单的解决方案是删除详细信息的UINavigationController。 使用以下示例中显示的设置。 但是,使用此方法存在一个主要缺点 :没有用于非折叠拆分视图的导航栏。 您可能需要使用导航栏来显示外观,标题,或者更重要的是在详细视图控制器中放置导航项。

通过实现UISplitViewControllerDelegate的两种方法:我们可以在折叠状态下显示详细信息时动态移除多余的导航控制器,并且在从折叠状态展开时也可以重新添加导航控制器。

删除UNavigationController

splitViewController(_:showDetail:sender 🙂

询问委托人是否要执行在拆分视图界面的第二位置显示视图控制器的工作。

在折叠的拆分视图中显示详细信息视图控制器时删除导航控制器

第4行:检查以确保拆分视图已折叠,您只想删除处于折叠状态的导航控制器。

第4行:确保vc(视图控制器)是UINavigationController,这将停止无限递归。

第5行:从导航控制器中获取详细视图控制器。

第6行:使用detailVC手动触发显示详细信息(无需嵌入UINavigationController中)。

第7行:返回true表示我们自己处理了过渡。

重新添加UNavigationController

splitViewController(_:separateSecondaryFrom 🙂

要求委托人为拆分视图界面提供新的辅助视图控制器。

扩展到未折叠的拆分视图时,向后添加导航控制器

第5行:检查明细视图控制器是否在导航堆栈的顶部。

第6行:从主菜单的导航控制器中弹出局部视图控制器。

第7行:将详细信息视图控制器嵌入到其自己的导航控制器中。

第9行:返回嵌入在其自己的导航控制器中的局部视图控制器。

第11行:检查master是否在导航堆栈的顶部。

第12-13行:通过情节提要创建新的detailVC

第14至16行:设置导航项以匹配MasterViewController的prepare for segue方法。

https://github.com/edwurtle/SplitViewTitleBug