使用 UISearchController 时,iOS 13 UIBarButtonItem 不可点击和重叠 UINavigationBars

Posted

技术标签:

【中文标题】使用 UISearchController 时,iOS 13 UIBarButtonItem 不可点击和重叠 UINavigationBars【英文标题】:iOS 13 UIBarButtonItem not clickable and overlapping UINavigationBars when using UISearchController 【发布时间】:2019-09-27 12:32:06 【问题描述】:

我有一个导航栏,其中包含一些 UIBarButtonItem 按钮和一个 UISearchBar 像这样连接

var searchController: UISearchController!

override func viewDidLoad() 
    super.viewDidLoad()

    title = "Test"

    tableView.delegate = self
    tableView.dataSource = self

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

    // This leads to the bug
    searchController.hidesNavigationBarDuringPresentation = false

    navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(leftTapped))
    navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(rightTapped))

场景:我点击搜索栏,然后点击取消。

问题 1:条形按钮对触摸没有反应,除非我触摸屏幕的最外层像素(仅通过模拟器和鼠标点击才有可能)。

问题 2:当我推动另一个视图控制器时,导航项重叠

当我使用 hidesNavigationBarDuringPresentation = true 时,它会像预期的那样工作。


该问题出现在使用 Xcode 11.0 和 11.1 的缺口和非缺口 iPhone ios 13.0 和 13.1 上。

这是整个测试项目: https://github.com/fl034/HidesNavigationBarDuringPresentationTest


我已经提交了一份雷达文件(你也应该提交),但也许你们中的一些人已经有了解决方法?


更新 1:iOS 13.1.1 中仍然存在错误


更新 2:在 iOS 13.2 测试版中修复了错误(感谢 @Ben Gomm)

【问题讨论】:

我也注意到了这一点 - 必须将 hidesNavigationBarDuringPresentation 设为 true 以避免此错误,但这不是我想要的外观。我认为这是一个错误。启用大标题后,取消搜索栏似乎会出现第二个大标题,该标题不会随滚动视图的其余部分一起滚动。 非常不错的演示,但您应该消除所有对演示错误而言不必要的内容。您不需要标签栏控制器。您不需要栏按钮项目!只需点击表格行进行导航就足以表明导航栏已损坏。 同意。除了我需要条形按钮来证明条形按钮不再可点击。 在 iOS 13.1.2 上仍然损坏 我遇到了同样的问题,但我不能将 hidesNavigationBarDuringPresentation 设置为 true,因为当 UISearchBar 是第一响应者时,我仍然需要显示条形按钮 【参考方案1】:

视图调试器揭示了这个错误发生了什么。正在复制导航栏的内容。以下是显示搜索之前导航栏的外观:

这是之后的样子:

两个副本视图和额外的 UILabel 是问题所在。我不知道他们在那里做什么,也找不到删除它们的方法。

编辑顺便说一句,我认为 Apple 的一些应用程序显示了相同的错误。更容易查看您是否有大标题,因为这样您就可以同时看到大标题和额外标签:

【讨论】:

【参考方案2】:

我现在正在使用此解决方法,因为我希望我的大多数用户在搜索处于活动状态时都能看到导航栏(出于几个特定于 app-ux 的原因)。

var isIosVersionWithNavigationBarBug: Bool 
    if #available(iOS 13.2, *) 
        return false
    
    if #available(iOS 13.0, *) 
        return true
            
    return false

在我的搜索控制器中,我这样使用它

mySearchController.hidesNavigationBarDuringPresentation = isIosVersionWithNavigationBarBug

因此,如果 iOS 13.2 正在发布并且用户对其进行了更新,那么解决方法将不再适用。

【讨论】:

@n8gray 这不是真的,#available 绝对是运行时检查。资料来源:我们在超过 2000 万用户下载且从未出现过问题的应用中使用此功能。它甚至在您提供的链接中说:“如果您只想检查用户是否至少运行特定版本”,请使用#available @simonthumper:没错。不知道我在想什么。遗憾的是 Swift 选择使用 # 字符来标记在编译时评估的两个值(如#if运行时检查如#available。在这方面 C 更好。 这绝对是一个奇怪的!做出了一些奇怪的决定,但总的来说我是粉丝!只是想确保发现此内容的其他人不会感到困惑:)【参考方案3】:

这似乎在 iOS 13.2 beta 中得到修复,我使用 Xcode 11.2 beta (11B41) 测试了上面的示例项目。

【讨论】:

【参考方案4】:

并不为此感到自豪,但我现在通过这个 hack 让它工作了。

override func viewWillDisappear(_ animated: Bool) 
    super.viewWillDisappear(animated)
    let viewsToRemove = self.navigationController?.navigationBar.subviews.flatMap( (view) in
        view.subviews.filter  type(of: $0) == UILabel.self 
    )
    viewsToRemove?.forEach  $0.removeFromSuperview() 

【讨论】:

这仅修复了双倍的标题标签。激活一次搜索后,Sill 无法单击我的栏按钮项。

以上是关于使用 UISearchController 时,iOS 13 UIBarButtonItem 不可点击和重叠 UINavigationBars的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS 13 中使用 UISearchController 时,状态栏在 iOS 中变为白色

将 UISegmentedControl 与 UISearchController 一起使用

将 unwind segue 与 UISearchController 一起使用时出错

按下取消按钮时如何防止 UISearchController 关闭?

推送新的 UIViewController 时 UISearchController 消失

当 UISearchController 获得焦点时重置 UIView