danqing
danqing

Reputation: 3668

Unable to add UISearchController's search bar into navigationbar and delegate methods not getting called

I want to achieve something very simple: a search bar in the navigation bar, with a Cancel button that shows when the bar is activated.

I am using a UISearchController, and currently I have the following:

override func viewDidLoad() {
  super.viewDidLoad()
  ...

  let searchController = UISearchController(searchResultsController: nil)
  searchController.searchResultsUpdater = self
  searchController.delegate = self
  searchController.searchBar.delegate = self
  searchController.hidesNavigationBarDuringPresentation = false
  searchController.searchBar.sizeToFit()
  self.navigationItem.titleView = searchController.searchBar
  self.definesPresentationContext = true
}

The search bar shows. However, if I focus on it no Cancel button is shown, and no delegate methods are called whatsoever. That is, no methods in the UISearchResultsUpdating, UISearchControllerDelegate, or UISearchBarDelegate protocols are called, although I've set self to respond to all of them.

If I put the following line into viewDidLoad, the delegate methods start to function:

self.navigationItem.searchController = searchController

However, then I can't put the search bar inside the navbar. It's shown under the navbar instead.

I've searched extensively in SO but nothing seems to work for me. I may be missing something obvious here - how can I make it work? Thanks!

Upvotes: 2

Views: 1346

Answers (3)

Yuriy
Yuriy

Reputation: 53

Call this

self.navigationItem.titleView = searchController.searchBar

from viewWillAppear(), not from viewDidLoad(). And delegates methods works fine.

Upvotes: 1

Hitesh Surani
Hitesh Surani

Reputation: 13577

Just define UISearchController as property then everything working fine.

I have tested below in the sample project.

  class ViewControllerName: UIViewController{
       let searchController = UISearchController(searchResultsController: nil)

        override func viewDidLoad() {
            super.viewDidLoad()
            let search = UISearchController(searchResultsController: nil)
            self.navigationItem.searchController = search
            self.navigationItem.searchController!.searchBar.delegate = self
            self.navigationItem.searchController!.searchResultsUpdater = self
            self.navigationItem.searchController?.searchBar.showsCancelButton = true
        }

       func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
            print("Called")
        }

        func updateSearchResults(for searchController: UISearchController) {
            print("Called")
        }
    }

Hope it will work for you.

Upvotes: 1

dahiya_boy
dahiya_boy

Reputation: 9503

I have tried this code and everything working prop

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate, UISearchResultsUpdating {


@IBOutlet weak var tblView: UITableView!


override func viewDidLoad() {
    super.viewDidLoad()
    :
    :

    let search = UISearchController(searchResultsController: nil)
    self.navigationItem.searchController = search
    self.navigationItem.searchController!.searchBar.delegate = self
    self.navigationItem.searchController!.searchResultsUpdater = self
    self.navigationItem.searchController?.searchBar.showsCancelButton = true

    :
    :
}

Tested below delegates and both are called as expected.

func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
    print("search end editing.")
}

func updateSearchResults(for searchController: UISearchController) {
    print("update search results ... called here")
}

UI:

enter image description here

Upvotes: 0

Related Questions