iOS: 将搜索栏添加到主从应用程序中的导航栏

iOS: Adding a search bar to the navigation bar in a master detail app

我做了什么?

我使用 Xcode 9 模板在 Swift 中创建了一个具有核心数据支持的通用主从应用程序。

我想要什么?

我想在详情的导航栏中添加一个搜索栏。

我是怎么做到的?

let searchController = UISearchController(searchResultsController: nil)
navigationItem.searchController = searchController

发生了什么? (实际问题)

详细信息的导航栏中没有出现搜索栏。相反,导航栏失去了它的阴影线,当我回到主界面时,搜索栏出现在动画时间的导航中,然后消失。

这个问题只发生在我 运行 iPhone 上的代码,而不是 iPad(或横向模式下的 iPhone)上的拆分视图左边是主视图,右边是详细视图。

对我来说,导航栏似乎有问题,但我就是无法理解它。

您可以在 Github 上下载示例项目 here

我已经将它隔离到从 table 视图项到 {NavigationController-DetailViewController} 的 segue(kind = Show Detail(例如 Replace))。那个 segue 的工作是替换细节在拆分视图中查看控制器,或在紧凑模式下推送详细视图控制器。

例如,如果撕掉 Show Detail(例如 Replace)segue,并使用“Show(例如 Push)”segue 类型将 table 视图单元直接连接到 DetailViewController,则 UISearchBar将按预期显示。

对于这种情况,看起来 segue 正在以影响搜索栏内的搜索控制器的方式呈现视图控制器。设备之间的代码路径差异很大,这可以解释为什么它可以在 iPad.

上运行

Apple 的开发人员技术支持已确认这是 iOS 中的错误。

一种廉价的解决方法是使用自定义 segue 手动执行自适应呈现(推送或替换):

class PushOrPresentSegue: UIStoryboardSegue
{
    override func perform() {
        let splitVC = self.source.splitViewController
        let destVC = self.destination
        let nav = destVC as! UINavigationController
        let topVC = nav.topViewController

        if (splitVC?.traitCollection.horizontalSizeClass == .regular) {
            // Replace
            let splitViewControllerVCs = splitVC?.viewControllers
            splitVC?.viewControllers = [splitViewControllerVCs![0], destVC];
        }
        else
        {
            // Push
            let sourceVC = self.source
            sourceVC.navigationController?.pushViewController(topVC!, animated: true)
        }
    }

}

在 Storyboard 中,必须将 Master View Controller 的单元格与 Detail ViewContorller 的 Navigation Controller 之间的连接更改为:Kind = Custom, Class = PushOrPresentSegue