Dean Davids Dean Davids - 1 month ago 12x
iOS Question

UISearchBar will not respond in UISplitviewController Master

I have a pretty standard setup of

as master controller in
, universal

Again, standard fare, I inserted a
as the header of the table.

self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.searchController.dimsBackgroundDuringPresentation = NO;
self.searchController.hidesNavigationBarDuringPresentation = NO;

[self.searchController.searchBar sizeToFit];
self.tableView.tableHeaderView = self.searchController.searchBar;

self.definesPresentationContext = YES;

No need for showing the rest of my code, the search and all work as expected, on the
. My issue is that the search bar does not ever receive focus or present the keyboard when run on
. No response, seems not to receive touches. Does not even respond to programmatically attempting to

Nothing happens.

The search bar is visible and placed appropriately, there are no underlay or overlay issues.

It works fine on
. Receives touch, presents keyboard, search works. Presumably there is a critical difference in presentation when
is collapsed. With hours of search, pouring through the documentation and every tutorial I come across, I have not found a similar experience which is surprising.

Additional note: If I use multi tasking to shrink the split view to collapsed on iPad, the search bar then works, same as on
. It definitely has to do with the collapsed state of the split view.

UPDATE: (Getting closer)

After further experimentation I find that the search bar works on the iPad if you start the app in landscape. In portrait mode, my primary controller is hidden. It slides in by selection of the
, which is set to the
of the detail controller. That is when the searchBar breaks and no longer will respond to touches.

If I start in landscape, then rotate to portrait, it stops working as well. Rotating back to landscape does not fix it. Once broke, it stays broke until a restart.

I tried moving
to the
method of the master controller, but that had no effect.

Further Update:

Another unexpected circumstance is that there is no problem with the search bar at all on iPhone 6plus. Works regardless of orientation, collapsed or no and doesn't matter which state it starts in. I would expect this would be same as iPad when in landscape orientation. Works completely on

I still have not figured this out. My latest attempt to fix, I moved all the search controller initialization to the
method. No change whatsoever.

Also, I noticed that when the search is active, keyboard onscreen, if I rotate the iPad the keyboard goes away but the search bar remains active. I didn't realize at first, then I saw the cancel button still displayed. It won't receive touches and does not have keyboard, but it is apparently still first responder.

Sample Project Uploaded to GitHub:
Github Repository

NOTE- There was no issue until I added my UISplitview Delegate methods to the project. I wanted to add this to my question right away, so, I haven't yet even tried to see exactly how these delegate methods affect the search bar but obviously the issue is created there somewhere.

I tried a few more variations with no success.

  • Move search bar to section header. No joy.

  • Put search bar in a UIView as a content view. No joy.

  • Remove search bar on disappear, reinsert on did appear. No joy.

  • Manipulate the size of search bar frame to ensure it is not clipped. No joy.

I also looked at the view hierarchy in profiler, the search bar is top level, not covered by anything else.


This is clearly a bug in UISplitViewController and/or UISearchController. Certainly file a radar w/ Apple and attach your code sample.

I think the bug involves UISplitViewController.displayMode UISplitViewControllerDisplayModeAutomatic. When I change the preferredDisplayMode to UISplitViewControllerDisplayModeAllVisible then everything starts to work:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
    UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
    navigationController.topViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem;
    splitViewController.delegate = self;
    splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible;

    return YES;

The main thing this changes is the default layout for portrait on iPad, which I understand may not be ideal. I also played with setting preferredDisplayMode to UISplitViewControllerDisplayModeAllVisible initially then setting it back to UISplitViewControllerDisplayModeAutomatic; this worked great until the screen orientation changed - then it all broke again. You might have some luck going further down that path.

I also made the following addition in the AppDelegate, to force the search controller to deactivate on displayMode change. (I also had to expose the searchController property publicly on the MasterViewController).

- (void)splitViewController:(UISplitViewController *)svc willChangeToDisplayMode:(UISplitViewControllerDisplayMode)displayMode {

    UINavigationController *navigationController = [svc.viewControllers firstObject];
    MasterViewController* mvc = (MasterViewController*) navigationController.topViewController;
    [mvc.searchController setActive: NO];