4
votes

I'm having the same problem as here, which doesn't have any answers. (Setting searchController.active to false clears out the search text, which I don't want.) I want to use a UISearchController so that users can search through the list of items in my UITableView. I have a show segue hooked up in the Interface Builder that triggers when the table view's cell is selected. The problem is that if the user searches for something and then clicks on a cell of the table, when it segues to the new view, the search bar just sits there. Ideally, I would like the navigation bar to be "replaced" by the search bar while the user is searching, then have the navigation bar return when the user clicks on a cell, and then have the search bar come back when the user clicks the "Back" button. (This is the way the now-deprecated UISearchDisplayController would work.) How can I accomplish this? Here is the controller for my table view.

class ItemSearchViewController: UITableViewController, UISearchResultsUpdating
{
    var searchController: UISearchController?

    let itemList = [ItemList(category:"Chocolate", name:"chocolate Bar", price: 1234),
    ItemList(category:"Chocolate", name:"chocolate Chip", price: 1234),
    ItemList(category:"Chocolate", name:"dark chocolate", price: 1234),
    ItemList(category:"Hard", name:"lollipop", price: 1234),
    ItemList(category:"Hard", name:"candy cane", price: 1234),
    ItemList(category:"Hard", name:"jaw breaker", price: 1234),
    ItemList(category:"Other", name:"caramel", price: 1234),
    ItemList(category:"Other", name:"sour chew", price: 1234),
    ItemList(category:"Other", name:"gummi bear", price: 1234)]

    var filteredList : [ItemList] = []

    override func viewDidLoad()
    {
        super.viewDidLoad()

        self.title = "Item Search"
        self.tableView.delegate = self
        self.tableView.dataSource = self

        self.searchController = UISearchController(searchResultsController: nil)
        self.searchController!.searchResultsUpdater = self
        self.searchController!.hidesNavigationBarDuringPresentation = true
        self.searchController!.dimsBackgroundDuringPresentation = false
        self.searchController!.searchBar.searchBarStyle = .Minimal
        self.searchController!.searchBar.sizeToFit()
        self.tableView.tableHeaderView = self.searchController!.searchBar  
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
    {
        if (segue.identifier == "itemDetail")
        {
            let itemDetailViewController = segue.destinationViewController as UIViewController
            let selectedCell = sender as UITableViewCell
            itemDetailViewController.title = selectedCell.textLabel?.text
        }
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
    {
        let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell
        var item : ItemList

        if self.searchController!.active
        {
            item = self.filteredList[indexPath.row]
        }
        else
        {
            item = self.itemList[indexPath.row]
        }

        cell.textLabel!.text = item.name
        return cell
}

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
    {
        if (self.searchController!.active)
        {
            return self.filteredList.count
        }
        else
        {
            return self.itemList.count
        }
    }
}

extension ItemSearchViewController: UISearchResultsUpdating
{
    func updateSearchResultsForSearchController(searchController: UISearchController)
    {
        if (searchController.searchBar.text.isEmpty)
        {
            self.filteredList = self.itemList
        }
        else
        {
            let searchPredicate =
            {
                (item: ItemList) -> Bool in
                item.name.rangeOfString(searchController.searchBar.text, options: .CaseInsensitiveSearch) != nil
            }
            self.filteredList = self.itemList.filter(searchPredicate)
        }
        self.tableView.reloadData()
    }
}
1

1 Answers

3
votes

Add this line in viewDidLoad()

definesPresentationContext = true

From the documentation for definesPresentationContext

A Boolean value that indicates whether this view controller's view is covered when the view controller or one of its descendants presents a view controller.

Discussion

When a view controller is presented, iOS starts with the presenting view controller and asks it if it wants to provide the presentation context. If the presenting view controller does not provide a context, then iOS asks the presenting view controller's parent view controller. iOS searches up through the view controller hierarchy until a view controller provides a presentation context. If no view controller offers to provide a context, the window's root view controller provides the presentation context.

If a view controller returns true, then it provides a presentation context. The portion of the window covered by the view controller's view determines the size of the presented view controller's view. The default value for this property is false.