UISearchController and darker barTintColor under iOS 13

I'm facing a few problems with UISearchController under iOS 13.


I'm using a UISearchController within a UITableViewController in order to search for something within the table.



The first problem occurs if the TableView only has a few items, so that there's a lot of unused room at the bottom of the TableView. When the UITableViewController is shown, the search field is hidden, just as it is supposed to. But once I start scrolling to make the search field visible, it is absoultley impossibel to scroll back in order to hide the search field again. This only works if there are more cells in the table that will fit on screen. This doesn't look very nice. This issue occurs on both iPad and iPhone.


Is there a way to hide the search field by scrolling again, just like it is supposed to work and like it is working when enough cells are available?



The second problem is a big one and occurs if I set a darker barTintColor for the navigation toolbar (and a bright or white tint color to the navigation toolbar buttons and texts). Whenever I scroll down to reveal the search field, the whole navigation toolbar (including the area with the search field) will change its color and will get the color of the background color of the TableView (usually white or light gray for the "grouped" tables). This makes the search field, the icons and title of the navigation toolbar totally unreadable, because they still have the same bright/white color as before.

I thought that this might be intended behavior when the searchBar.searchBarStyle property is set to .minimal, but this doesnät seem to be the case, because it also happens when using .prominent.

This issue only occurs on the iPad, but not on the iPhone


Is there a way to make sure that the navigation toolbar does not change its color when scrolling the search field into view? With using the default colors (white navigation bar) this is not a big deal and hardly noticable, but with other colors this can get ugly.


BTW: the issue with the colors does not happen in the simulator, only on a real device. But this might be because of the iOS release: the simulator only supports iOS 13.0, while the real device uses iOS 13.1.3. Sothis might be one of the many new bugs of iOS 13



This is how I create the UISearchController:


override func viewDidLoad() {
    super.viewDidLoad()

    searchController = UISearchController(searchResultsController: nil)
    searchController?.hidesNavigationBarDuringPresentation = false
    searchController?.dimsBackgroundDuringPresentation = false
    searchController?.obscuresBackgroundDuringPresentation = false
    searchController?.searchResultsUpdater = self
    searchController?.searchBar.searchBarStyle = .prominent
    navigationItem.searchController = searchController
    navigationItem.hidesSearchBarWhenScrolling = true



Both of the above issues do look extremly ugly, so my current "workaround" is to always show the search field (using navigationItem.hidesSearchBarWhenScrolling = false). This is not really what I want, but at least it doesn't look as ugly.

Replies

When the UITableViewController is shown, the search field is hidden, just as it is supposed to

That's not what happens when search is created in IB.


I would need to test in your exact configuration.

When I try it, I'm asked to add

searchController.searchResultsUpdater = self as! UISearchResultsUpdating

leading later to a crash.


Could you show some more code, with the class and objects declarations.

There's not much more code I can show. Just create a simple new project with a TableViewController as the rootview controller. Use the following (complete) code for this view controller. The code just creates a few empty dummy cells and sets an empty dummy SearchResultsUpdater. Run the App on an iPad (iPadOS 13.1.3) and you'll see the problems.



Problem 1:

While pulling down the table, the navigation toolbar will change its color (the icons and title keep

their original color), so when the search field is fully visible, the navigation bar shows a white

background with white buttons and title, making the navigation toolbar completely unusable


Tapping into the search field immediatelly changes the colors of the navigation toolbar again to its

original dark appearance. Canceling the search immediatelly turns the navigation toolbar all white again.


This is only an issue on a real iPad device (iOS 13.1.3), there's no problem on the simulator (iPadOS 13.0)



Problem 2:

Once the search field was made visible, you can no longer hide it. Hiding the search field is only

possible if the table contains enough cells to fill the whole screen.


This is always an issue (iPad, iPhone and simulator)


Problem 3:

Setting a tableFooterView makes the search field initially hidden, if no footer is set, the search field

is initially visible. Why should a tableFooterView affect the search bar?



So the whole UISearchController is currently more or less completely broken and useless, unless you're using a bright navigation toolbar with dark icons and title and the table has alwas more cells than fit on the screen, or alternatively configure the searchbar to be visible all the time and never hide it while scrolling.


Is there any way to make it work with a dark barTintColor?



import UIKit

class ViewController: UITableViewController {

    var searchController: UISearchController?
  
    override func viewDidLoad() {
        super.viewDidLoad()

        self.navigationController?.navigationBar.barTintColor = UIColor(white: 0.3, alpha: 1)
        self.navigationController?.navigationBar.tintColor = UIColor(white: 1, alpha: 1)
        self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white];

        searchController = UISearchController(searchResultsController: nil)
        searchController?.hidesNavigationBarDuringPresentation = false
        searchController?.dimsBackgroundDuringPresentation = false
        searchController?.obscuresBackgroundDuringPresentation = false
        searchController?.searchResultsUpdater = self
        searchController?.searchBar.searchBarStyle = .prominent
        navigationItem.searchController = searchController
        navigationItem.hidesSearchBarWhenScrolling = true
      
        tableView.tableFooterView = UIView()
    }

  
  
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 5
    }
  
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        return UITableViewCell(style: .default, reuseIdentifier: nil)
    }

}


extension ViewController : UISearchResultsUpdating, UISearchControllerDelegate {
    func updateSearchResults(for searchController: UISearchController) {
        // find and update the search results
    }
}

I tried it but the search bar never shows.

Just an addition: Of course you need to embed the TableViewController into a UINavigationController (for example in the storyboard), otherwiese you won't see a Navigation toolbar at all. But then the above code should work just as described.

Thanks, that works now.



So, I tested with your set up:


Problem 1:

While pulling down the table, the navigation toolbar will change its color (the icons and title keep

their original color), so when the search field is fully visible, the navigation bar shows a white

background with white buttons and title, making the navigation toolbar completely unusable


Tapping into the search field immediatelly changes the colors of the navigation toolbar again to its

original dark appearance. Canceling the search immediatelly turns the navigation toolbar all white again.


This is only an issue on a real iPad device (iOS 13.1.3), there's no problem on the simulator (iPadOS 13.0)


If you set the navigation bar tint to system gray color instead of Default, and not translucent, it seems the problem disappear.


You may have to set the coloor of text field

        navigationItem.searchController?.searchBar.searchTextField.backgroundColor = .white

Ok for you ?


Problem 2:

Once the search field was made visible, you can no longer hide it. Hiding the search field is only

possible if the table contains enough cells to fill the whole screen.


This is always an issue (iPad, iPhone and simulator)


A few questions:


The closest I found to what you want is to set the searchBar inside the tableView (as a header).

Then you can hide it by setting it to nil or reverting to the original value.

But once again, why to hide it ?


Problem 3:

Setting a tableFooterView makes the search field initially hidden, if no footer is set, the search field

is initially visible. Why should a tableFooterView affect the search bar?


The last post here

https://stackoverflow.com/questions/43542508/hiding-tableview-tablefooterview-causes-my-section-headerview-to-disappear

gives some explanation (but not totally convincing).


And reading a lot of forum show it nis really tricky (no one really explained what happens here).

If you set the navigation bar tint to system gray color instead of Default, and not translucent, it seems the problem disappear.


I'm not sure if I can follow, sorry. But in my code I've set the barTintColor of the navigation bar to a darker gray. With the default white there is no problem - or in other words: there's exactly the same happing when using the default colors from the technical point of view: the color of the navigation toobar will change into the background color of the table view when making the search field visible, but because the default white of the navigation bar and the white/bright table background are so similar, so there's no "visual" issue noticable. But of course the darker the navigation bar color the bigger the problem will be...


If I set the "isTranslucent" property of the navigation bar to false, then the navigation bar won't change to white anymore, but unfortunately this isn't a help at all, because now it will change to complete black when the search bar gets visible. And this is also not a great option, because neither black nor white really fits into my App, is pretty ugly and not what I would expect.



The closest I found to what you want is to set the searchBar inside the tableView (as a header).

Then you can hide it by setting it to nil or reverting to the original value.


Yes, this would work, though of course then the whole searchbar would be no longer be visually part of the navigation bar, which is why Apple has introduced the searchController property for the navigationItem in the first place in IOS 11. Apple's new design has made both elements a visual unit and I would like to keep this.


But once again, why to hide it ?


Because though searching is an important feature, it is not really used all the time. So the search bar should be hidden by default but still be reachable anytime when you actualy need it. Especially on smaller iPhone models with a small screen it can be useful to have more room for important stuff and get the search bar only when you actually want to search something.



BTW: All these issues are only an issue under iOS 13. Under iOS 11 and 12 you can hide the search bar again by scrolling even if the table only contains a few cells, ans also the color of the navigation toolbar does not change. The color issue is also not visible in the simulator, but becaise the simulator is only available with iOS 13.0, I assume this is actually a new bug of iOS 13.1.x

I understand your points. It appears that we have not total control (or at least I could not find) over the way navigation bar work.


If you get answer from bug report or from Apple support, thank you to post it here.


Good luck.

One point is solved now: The issue with the colors can be solved with the new UINavigationBarAppearance API. But the other issues remain.

Thanks a lot, your post made my day after two days of frustrations ... the property scrollEdgeAppearance of UINavigationBarAppearance finally made the trick.


With regards to your other problem I filed a RADAR in January 2018 without any success so far.


Greetings, Mattes