推送下一个视图控制器时删除 UISearchBar 的延迟

Posted

技术标签:

【中文标题】推送下一个视图控制器时删除 UISearchBar 的延迟【英文标题】:Delay in UISearchBar being removed when pushing next view controller 【发布时间】:2019-02-19 13:03:21 【问题描述】:

Xcode 10.1、Swift 4.2

ViewController A 有 LargeTitlesUISearchControllerUITableView 在运行。

在选择 TableViewCell 后推送 ViewController B(也是 TableView)时,UISearchBar 占用的空间会出现延迟,如动画所示。

ViewController B 也有一个 UISearchController,但按照通常的行为,它是隐藏的,直到用户在屏幕上向下拖动。

有谁知道如何防止这种情况发生?

其他信息和代码:

ViewController A 当单元格被点击时,它使用 Show (e.g Push) segue 在 Storyboard 上选择 Animates 来推动 ViewController B。使用 prepareForSegue 方法注入数据。

performSegue(withIdentifier: "showLogbook", sender: self)

视图控制器 B:

class LogbookVC: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate, UISearchResultsUpdating 

    //Extract
    private let searchController = UISearchController(searchResultsController: nil)


    @IBOutlet private var addButton: UIBarButtonItem!
    @IBOutlet private var shareButton: UIBarButtonItem!
    @IBOutlet private var backButton: UIBarButtonItem!
    @IBOutlet private var tableView: UITableView!

    override func viewDidLoad() 
        super.viewDidLoad()

        tableView.delegate = self
        tableView.dataSource = self
        tableView.rowHeight = 75.0
        //loading tableView data


override func viewWillAppear(_ animated: Bool) 
    super.viewWillAppear(animated)
    self.navigationController?.navigationBar.prefersLargeTitles = true
    self.definesPresentationContext = true
    configureSearchController()
    fetchAndSortLogEntries()


private func configureSearchController() 
    navigationItem.searchController = searchController
    searchController.searchResultsUpdater = self
    searchController.searchBar.scopeButtonTitles = ["Newest", "Oldest"]
    searchController.searchBar.delegate = self
    searchController.searchBar.barStyle = .black
    searchController.searchBar.tintColor = K.Colors.appMid
    searchController.searchBar.keyboardAppearance = .dark
    searchController.searchBar.returnKeyType = .done
    searchController.dimsBackgroundDuringPresentation = false
    let attributes = [NSAttributedString.Key.foregroundColor: K.Colors.appMid]
    UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]).setTitleTextAttributes(attributes, for: .normal)
    searchController.searchBar.setValue("Reset", forKey: "_cancelButtonText")
    let searchBarCancelButton = searchController.searchBar.value(forKey: "cancelButton") as? UIButton
    searchBarCancelButton?.setTitle("Reset", for: .normal)

【问题讨论】:

你能告诉我们你是如何从 A 展示 ViewControllerB 的吗? 我猜问题完全出在第二个视图控制器上。您确定搜索栏最初是隐藏的,而不是隐藏在 viewDidAppear 中吗? 更新了一些代码,感谢查看。 如果我没有在 ViewController B 中配置 searchController,那么 TableView 会正确显示,所以问题出在某个地方。注释掉 configureSearchController 中的各行没有区别,问题仍然存在。我将创建一个基本的测试项目,看看是否可以在那里重现问题。 【参考方案1】:

我认为这是使用LargeTitles 并在相邻的ViewControllers 中有两个UISearchControllers 时的错误。

我发现通过在viewDidAppear 中将UISearchController 添加到NavigationItem 可以解决问题,但是必须异步添加,否则会出现以下致命错误:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Only one palette with a top boundary edge can be active outside of a transition.

此代码需要同时添加到ViewControllers,以便在导航回 ViewController A 时也可以防止问题行为。

Xcode 10.1、Swift 4.2

    override func viewDidAppear(_ animated: Bool) 
        super.viewDidAppear(animated)
        DispatchQueue.main.async 
            self.navigationItem.searchController = self.searchController
            self.searchController.searchResultsUpdater = self
            self.searchController.searchBar.delegate = self
        
    

此代码将确保在出现下一个ViewController 时不会隐藏NavigationBar

    override func viewWillDisappear(_ animated: Bool) 
        super.viewWillDisappear(animated)
        navigationController?.isNavigationBarHidden = false
    

【讨论】:

以上是关于推送下一个视图控制器时删除 UISearchBar 的延迟的主要内容,如果未能解决你的问题,请参考以下文章

如果推送控制器隐藏标签栏,UISearchBar 会跳转

将 UISearchBar 与表视图控制器一起使用并转到另一个视图时显示问题

UISearchBar 在活动时与 UITableView 内容重叠

UISearchBar 设置为 titleView 在 push segue 上的行为很奇怪

模态下的弹出/推送视图

当 UISearchBar 成为横向的第一响应者时,模态视图移动