SearchBar in NavigationBar IOS 11

I tried using Navigation Bar Large Title and adding Search Bar to Navigation Controller. The Search Bar is displayed under the Navigation title. It should be hidden until I swipe down. I understand that the default behavior is hidden unless I set "navigationItem.hidesSearchBarWhenScrolling = false". Even I add "navigationItem.hidesSearchBarWhenScrolling = true", it doesn't work.

I created a new app to test this function. It has ViewController and Navigation Controller embedded. Below is my code:


class ViewController: UIViewController {

     let searchController = UISearchController(searchResultsController: nil)

     override func viewDidLoad() { 
          super.viewDidLoad() 
          navigationController?.navigationBar.prefersLargeTitles = true
          navigationItem.searchController = searchController
          // navigationItem.hidesSearchBarWhenScolling = true

     } 
}

I think that the problem in your code is that you are using a UIViewController, which view property is a normal UIView (It is not a subclass of UIScrollView).


hidesSearchBarWhenScrolling:


When the value of this property is true, the search bar is visible only when the scroll position equals the top of your content view.


If you instead, for example, use a UITableViewController, which view property is a UITableView (It is a subclass of UIScrollView), all works as expected.

Thanks! It does work in UITableViewController or UIViewController + UITableView.


My problems are as follows

1. the Big Title not change to small title when scrolling;

2. the Search Bar stay permanently under the Navigation bar;

3. some pages are able to change to small tilte when scrolling.


I checked many many times still cannot figure out what is the problem. That's why I write this simple app to test. But this simple app run flawlessly. (of course it does not have any other codes, such as UITableViewDelegate.... and data)

I test in an App as follow, and:


1.The Big Title change to small title when scrolling


2. The Search Bar NOT stay permanently under the Navigation bar (In RootViewController), it stay permanently in SecondViewController (because it’s view property is a normal UIView).

3. Some pages are able to change to small tilte when scrolling (You control it by choosing between the different options of navigationItem.largeTitleDisplayMode)


(Is Initial ViewController) UINavigationController ————> class RootViewController: UITableViewController ————> class SecondViewController: UIViewController


In Interface Builder:

- In RootViewController:

- Set the Identifier of UITableViewCell to CellIdentifier.

- Add an UIBarButtonItem and from it, add a Push Segue to SecondViewController.


import UIKit
extension RootViewController: UISearchControllerDelegate{  

    func willPresentSearchController(_ searchController: UISearchController){
        print("\(type(of: self)) \(#function)")
    }
   
func didPresentSearchController(_ searchController: UISearchController){


print("\(type(of: self)) \(#function)")

}

func willDismissSearchController(_ searchController: UISearchController){


print("\(type(of: self)) \(#function)")

}

func didDismissSearchController(_ searchController: UISearchController){


print("\(type(of: self)) \(#function)")

}


func presentSearchController(_ searchController: UISearchController){

print("\(type(of: self)) \(#function)")

}

}

extension RootViewController: UISearchResultsUpdating {

func updateSearchResults(for searchController: UISearchController){

print("\(type(of: self)) \(#function)")

}

}

class RootViewController: UITableViewController {

let array = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30"]



let searchController = UISearchController(searchResultsController: nil)

override func viewDidLoad() {


super.viewDidLoad()

// Adopt Large Titles:

// Set up the navigation bar


navigationItem.title = "Custom Title"

navigationController?.navigationBar.prefersLargeTitles = true


searchController.delegate = self

navigationItem.searchController = searchController

navigationItem.hidesSearchBarWhenScrolling = true

}


override func numberOfSections(in tableView: UITableView) -> Int {

return 1

}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

return array.count

}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {


let cell = tableView.dequeueReusableCell(withIdentifier: "CellIdentifier", for: indexPath)

cell.textLabel?.text = array[indexPath.item]

return cell

}

}



- In SecondViewController choose between the different options of navigationItem.largeTitleDisplayMode:


import UIKit
extension SecondViewController: UISearchControllerDelegate{ 
  
    func willPresentSearchController(_ searchController: UISearchController){
        print("\(type(of: self)) \(#function)")
    }
  
    func didPresentSearchController(_ searchController: UISearchController){
        print("\(type(of: self)) \(#function)")
    }
  
    func willDismissSearchController(_ searchController: UISearchController){
        print("\(type(of: self)) \(#function)")
    }
  
    func didDismissSearchController(_ searchController: UISearchController){
        print("\(type(of: self)) \(#function)")
    }

    func presentSearchController(_ searchController: UISearchController){
        print("\(type(of: self)) \(#function)")
    }
}
extension SecondViewController: UISearchResultsUpdating {
    func updateSearchResults(for searchController: UISearchController){
        print("\(type(of: self)) \(#function)")
    }
}
class SecondViewController: UIViewController {
     let searchController = UISearchController(searchResultsController: nil)
  
    override func viewDidLoad() {
        super.viewDidLoad()
        // Automatically Choose Large Title
      
        navigationItem.largeTitleDisplayMode = .automatic  //.automatic -->  Keep the UINavigationBar in whichever state it was for the previous screen.
      
        //navigationItem.largeTitleDisplayMode = .always  //.always -->  Show the UINavigationBar with large titles regardless of which state it was in for the previous screen.
      
       // navigationItem.largeTitleDisplayMode = .never  //.never -->  Never display a large title.
      
        searchController.delegate = self
        navigationItem.searchController = searchController
      
        navigationItem.hidesSearchBarWhenScrolling = true
    }
}

Thanks for the details explanation and sample code. I will try it.

I found the problem is the Toolbar is on top of TableView in Storyboard. When I moved Toolbar under TableView, it works as expected, i.e. Large Title and hidden search bar. Thanks for help.

Which toolbar are you referring to, did you add it to your storyboard?

Yes. I am referring to the ToolBar added in the ViewController. I add ToolBar to all ViewControllers to make it looks consistence.

SearchBar in NavigationBar IOS 11
 
 
Q