Implementing navigation that supports going back to a search result

97 views Asked by At

I am looking to implement a search such that when the user presses a search result, the relevant UIViewController is pushed onto the search result itself, allowing the user to press back to view the search result again.

I have tried simply pushing the ViewController onto the presenting ViewController's UINavigationController. This results in the UIViewController appearing behind the search result (it can be seen when canceling the search result).

I have also tried subclassing UINavigationController and making it conform to UISearchResultsUpdating, proxying the updates to the UIViewController. This results in almost the correct behavior, but the search bar remains with the navigation bar when a view controller is being pushed onto the UINavigationController, as can be seen in the image below.

I could simply do some hacky code to hide/show the search bar depending on the state of the UINavigationController, but it seems like there must exist a cleaner way of accomplishing this.

Apple has themselves done this in their Notes app, if you do a search and press a result, you are brought to the relevant note, pressing back takes you back to the search result. So I am wondering how to replicate this behavior correctly.

enter image description here

1

There are 1 answers

0
dape On BEST ANSWER

I later solved this the hacky way by making the UIViewController that is responsible for displaying the search result conform to the UINavigationControllerDelegate protocol (in addition to UISearchResultsUpdating). The updateSearchResultsForSearchController(searchController: UISearchController) method then catches and stores a reference to the UISearchController that is passed as a parameter. Then this juggling with view-logic in the UINavigationControllerDelegate code makes everything work and look as expected:

func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
    if viewController == self {
        searchController.searchBar.hidden = false
        searchController.searchBar.becomeFirstResponder()
    } else {
        searchController.searchBar.hidden = true
        searchController.searchBar.resignFirstResponder()
    }
}

Lastly, as explained in the third paragraph above, I made a subclass of UINavigationController which is assigned as the search results controller, and which delegates navigation events and UISearchResultsUpdating events to the UIViewController.

This certainly works as intended and I not experienced any bugs with this so far. Will post an update if I find a cleaner solution next time I look over this code (might be easier in iOS 9).