UISearchController - 与子视图控制器不兼容

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UISearchController - 与子视图控制器不兼容相关的知识,希望对你有一定的参考价值。

我有一个问题,我当前的配置是:

UITableViewController - > UINavigationController - >一个ViewController,用于交换2个子视图控制器。

每个子视图控制器都有一个与之关联的UISearchController。当UISearchBar激活时,它似乎永远不会有正确的位置。

extension MySearchViewController: UISearchControllerDelegate {

    func willPresentSearchController(searchController: UISearchController) {
        var adjustedOrigin = searchController.searchBar.frame.origin
        //FIXME: There's some odd behavior with embedded child VCs where the status bar adjustments are not taken into consideration
        adjustedOrigin.y += UIApplication.sharedApplication().statusBarFrame.height
        searchController.searchBar.frame.origin = adjustedOrigin
        definesPresentationContext = false
        navigationController?.definesPresentationContext = true
        navigationController?.extendedLayoutIncludesOpaqueBars = true
    }

    func didPresentSearchController(searchController: UISearchController) {
        definesPresentationContext = true

    }

    func didDismissSearchController(searchController: UISearchController) {
        var adjustedOrigin = searchController.searchBar.frame.origin
        //FIXME: There's some odd behavior with embedded child VCs where the status bar adjustments are not taken into consideration
        adjustedOrigin.y -= UIApplication.sharedApplication().statusBarFrame.height

        searchController.searchBar.frame.origin = adjustedOrigin
    }

}

您可以在上面看到原点已经调整,因为我正在尝试手动校正UISearchBar的偏移量,这是迄今为止不首选的。我试图在故事板中检查(在许多区域中)显示器,并且几乎在层次结构中的所有地方都通过代码。我似乎无法找到抵消的罪魁祸首。默认情况下,UISearchBar将一直显示在状态栏下:

search screen

这是没有我的手动调整仍然有点偏。

有人有解决方案吗?


编辑1:

进一步证明父VC中的某些内容正在弄乱偏移量,UISearchBar的实际超级视图在呈现时会偏移-20。因此,以下更正了问题:

import UIKit

class MySearchController: UISearchController {

    override func viewDidLoad() {
        super.viewDidLoad()
        edgesForExtendedLayout = .Top
        extendedLayoutIncludesOpaqueBars = true
        automaticallyAdjustsScrollViewInsets = true 

        // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        print(active)

        if active && searchBar.superview!.frame.origin != CGPoint.zero {
            searchBar.superview?.frame.origin = CGPoint.zero
        }
    }
}
答案

以下是我发现的唯一方法,可以可靠地调整搜索控制器错误调整的状态栏偏移量。

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    //FIXME: Unfortunate hack required to adjust for offset of -20 pulled from ????? where ?????
    guard let searchBarContainerView = searchBar.superview where (active && searchBarContainerView.frame.origin != CGPoint.zero) else {
        return
    }
    searchBarContainerView.frame.origin = CGPoint.zero
}

请注意,物理原点被-20作为状态栏的高度所抵消。修正是为了确保原点强制设置为0。

另请注意,这是UISearchController子类中的重写方法。

另一答案

供将来参考:通常这种奇怪的关键是谁在定义表示上下文。

来自文档:https://developer.apple.com/documentation/uikit/uiviewcontroller/1621456-definespresentationcontext

当发生基于上下文的表示时,UIKit从呈现视图控制器开始并向上走动视图控制器层次结构。如果找到该属性值为true的视图控制器,则会要求视图控制器显示新的视图控制器。如果没有视图控制器定义表示上下文,UIKit会要求窗口的根视图控制器处理演示文稿。

因此,基本上您必须确保层次结构中的右视图控制器将definePresentationContext设置为YES。如果正确放置,则不需要偏移或框架修改。在您的情况下,可能是您的父VC需要定义表示上下文并确保没有子VC将其设置为YES。

以上是关于UISearchController - 与子视图控制器不兼容的主要内容,如果未能解决你的问题,请参考以下文章

UISearchController:用于显示和搜索的单个与单独的表格视图

如何在 tvOS 的同一视图中显示 UISearchController?

UISearchController 不会停留在表头视图的顶部

UISearchController 作为 UITableViewHeader

模态关闭时的 UISearchController 问题

在 UINavigationBar 上呈现 UISearchController 时推送视图控制器