Thomas Denney

UISearchController and definesPresentationContext

UISearchDisplayController has been the standard way to provide searching on a table view controller for the last five years, however it has always been a little broken and hard to use, so when it was replaced with UISearchController in iOS 8 I was relieved. You can find excellent examples of its usage here (Swift) and here (Objective-C).

Sadly, it turns out that UISearchController has its own issues as well, with the search bar sometimes covering the navigation bar, or content being visible under the status bar:

UISearchController problem

Thankfully, you can use This One Weird Trick to resolve these issues by setting the following in your main view controller (generally the table view controller that contains the search bar):

self.definesPresentationContext = YES;

So what’s going on here? The definesPresentationContext property is new in iOS 8, and the documentation states the following (emphasis mine):

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 YES, 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 NO.

The primary issue here is that when the search controller is presented it is presented modally it is going up the view controller hierarchy and checking with each view controller - generally a UITableViewController and then a UINavigationController - whether they can present the view controller. As definesPresentationContext is NO by default, the search controller is displayed modally across the whole screen (hence the issues with the status bar and navigation bar). By setting definesPresentationContext to YES you ensure that the search controller is presented within the bounds of the original table view controller.