UISearchController - 子视图控制器不兼容

4

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

UITableViewController -> UINavigationController -> 一个可切换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的偏移量,这远非理想。我已经尝试在storyboard和代码中的多个区域中取消勾选 从而取消显示,但几乎在整个层次结构中都找不到偏移源头。默认情况下,UISearchBar将显示在状态栏下方:

search screen

这是没有我的手动调整的情况下,但仍然有些偏差。

有人有解决方法吗?


编辑1:

进一步证明某个父VC中的内容正在干扰偏移量,实际上UISearchBar的superView的偏移量为-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
        }
    }
}

你有检查过 VC 的子视图中是否存在任何奇怪的约束吗? - brkr
我不确定你的意思。 UISearchController与子VC上的自动布局约束是分离的。唯一受影响的是UISearchBar(在呈现模式期间注入到UISearchController中的容器中)。 UISearchBar已设置转换掩码约束,以适当地不使用指定的约束基于布局。 - TheCodingArt
大多数情况下,这绝对是将某些东西传达给上级的事情,无论是在传达上下文偏移量的内容,我都知道。 - TheCodingArt
@TheCodingArt,你最终找到解决方法了吗? - jbouaziz
@jbouaziz,除了我使用的小技巧手动纠正我看到的行为之外,没有具体的答案。我将在下面附上一个答案,可能能够提供一些帮助。 - TheCodingArt
2个回答

0

供日后参考:通常在这种奇怪情况下的关键是谁定义了呈现上下文。

从文档中可以看到: https://developer.apple.com/documentation/uikit/uiviewcontroller/1621456-definespresentationcontext

当基于上下文的呈现发生时,UIKit 从呈现视图控制器开始并向上遍历视图控制器层次结构。如果它找到一个值为 true 的视图控制器,则请求该视图控制器呈现新的视图控制器。如果没有视图控制器定义呈现上下文,则 UIKit 请求窗口的根视图控制器处理呈现。

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


如果您参考上面的代码,那么确切的值已经被修改了但没有成功。我已经适当地设置了特定的标志,并且在制作时进行了操作以匹配我的预期,但没有成功。因此,除非您有一个适用于此情况的工作代码示例,否则此答案毫无意义,并且对问题的贡献不超过发布文档。 - TheCodingArt
我的感觉是你误解了definesPresentationContext的用法,因为你在willPresent中禁用它,在didPresent中重新启用,我认为这个标志告诉我们父/子VC层次结构中哪个视图控制器将负责呈现searchVC,因此应该在搜索栏的Presenter上将其设置为true,根据我的经验,当你必须调整偏移量、框架等来保持事物的位置时,通常意味着某些概念上的错误,希望这可以帮到你。 - PakitoV
我并没有误解用法,但没关系。在测试这种情况时,当初有一个原因要这样做。不过,这并没有提供解决方案,只是一种带有个人观点的评论。 - TheCodingArt

0

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

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子类中的重写方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接