13

I am using this code with no problem, but I would like to place the search controller below the navigation item’s titleView, instead of replacing it. With iOS11 it’s as easy as setting navigationItem.searchController to the searchController, and it will place it below the titleView, but in the navigationItem.

Any ideas on how to do this prior to iOS 11, instead of replacing the titleView?

Current Code:

if #available(iOS 11, *) {
    navigationItem.searchController = searchController
    navigationItem.hidesSearchBarWhenScrolling = false
} else {
    navigationItem.titleView = searchController.searchBar
}
Alec O
  • 1,697
  • 1
  • 18
  • 31
  • 1
    I think for iOS 10, you will have to make your own view similar to native functionality of iOS 11, since the default way of doing it was putting the search controller's view in title view. – Umar Farooque Oct 01 '17 at 17:44
  • Please don't post images of code. Post actual code, as text, copied and pasted into your question. Images can't be searched or referenced. – rmaddy Oct 01 '17 at 19:38

2 Answers2

27

I don't know if it's still relevant for you, but for anyone searching an answer and ending up here, this is a way to do it:

if #available(iOS 11.0, *) {
   navigationItem.searchController = searchController
} else {
   tableView.tableHeaderView = searchController.searchBar
}
Holger
  • 356
  • 4
  • 11
0

@holger's answer helps me fix my problem in iOS 10 - which it accidentally hide the whole navigation bar when pressing CANCEL.

Since my app has a logo sitting at the title of navigation bar, the search bar has to be hidden when not in use. So I added a search button as rightBarButtonItem, and trigger @holger's code when pressed.

@IBAction func onSearchAction(_ sender: UIBarButtonItem) {
    if #available(iOS 11.0, *) {
        navigationItem.searchController = searchController
    } else {
        // Fallback on earlier versions
        searchController.hidesNavigationBarDuringPresentation = false
        tableView.tableHeaderView = searchController.searchBar
    }
    searchController.isActive = true
}

func didPresentSearchController(_ searchController: UISearchController) {
    asyncAfter(.milliseconds(300)) {
        searchController.searchBar.becomeFirstResponder()
    }
}

By referring to another answer here, I added becomeFirstResponder() inside didPresentSearchController with a slight delay. So the keyboard will appears without tapping. Finally, implements UISearchControllerDelegate so that it will disappears when cancelled:

func willDismissSearchController(_ searchController: UISearchController) {
    if #available(iOS 11.0, *) {
        navigationItem.searchController = nil
    } else {
        // Fallback on earlier versions
        tableView.tableHeaderView = nil
    }
}
John Pang
  • 2,403
  • 25
  • 25