UISearchDisplayController on the iPad

February 4, 2011, 12:09 am

As a programmer you can create incredible stuff in surprisingly short periods of time. It doesn't get much more satisfying that adjusting your music volume to the cusp of permanent hearing damage, hunkering down for a couple of hours and cranking out something awesome. That is not what happened today when I tried to get my UISearchDisplayController to work correctly inside a UIPopoverController, on the iPad, in portrait mode.

In the first version of my Glossary apps I implemented the search bar functionality myself. That is I created my UISearchBar, I created a semi-transparent view that went over the top of the table view and I mucked around poking the UITableViewDelegate to get it to show my search results. It was all a bit of a horrible hack (it being my first iPhone app), but it worked (on the iPhone, in portrait mode).

The new implementation of my Glossary framework is a universal app (iPad and iPhone) and designed from the start to support arbitrary orientation. It became apparent very quickly that my old search code was not going to make it into the new version. On the iPhone the orientation stuff was a mess and on the iPad I was having to do a re-write anyway to support the UISplitViewController layout.

So I checked out the UISearchDisplayController and discovered it was awesome. It was easy to hook up to my existing table view delegate and basically it just worked out of the box. Well ... all except for one tiny 44 pixel hiccup.

In portrait mode, when you click the search bar, the UISearchDisplayController code animates the search bar so it is flush with the top border of the UIPopoverController. This looks great except that the black semi-transparent view covering the table view doesn't get re-sized correctly, so it is left with a 44 pixel (the height of the header that the search bar now covers) gap at the bottom of the popover view:

It works perfectly in landscape mode, I suppose because the view is being displayed in the left split view pane instead of in a popover view:

This is clearly a pretty simple bug in the UISearchDisplayController implementation, but it ate up a couple of commutes for me to develop a fairly horrible workaround:

NSLog (@"%d subviews", [self.searchDisplayController.searchContentsController.view.subviews count]); for (int i = 0; i < [self.searchDisplayController.searchContentsController.view.subviews count]; i++) { id view = [self.searchDisplayController.searchContentsController.view.subviews objectAtIndex:i]; NSRange rng = [[view description] rangeOfString:@"UIControl"]; if (rng.length != 0) { UIView * backgroundView = (UIView*)view; CGRect frame = backgroundView.frame; frame.size.height = self.searchDisplayController.searchContentsController.view.frame.size.height; backgroundView.frame = frame; } NSLog (@"%@", view); }

So this code is spinning through the subviews of the UISearchDisplayController until I find one that looks like the semi-transparent black background over the search results. When I find it, I lengthen it to match the height of the searchContentsController. The good news is that this works, it finds the right view and sets it's height correctly. The bad news is that it happens after the view has been added as a subview and so the user sees it briefly in it's buggy shortened state.

This code is in the searchDisplayControllerDidBeginSearch callback on the UISearchDisplayDelegate delegate. I tried moving the code to the searchDisplayControllerWillBeginSearch callback, and can adjust the view size at that point (before the user sees it, but the bug, causing the erroneous height adjustment, exists sometime after that callback, because by the time the view is displayed it has been shortened again.

I was surprised Googling the issue didn't garner any results and it is possible this because I have done something stupid or perhaps off the beaten track. If you can see the flaw in my logic, please let me know.

I should probably log a bug on this ...

Before I wrote this post I imagined that someone might be interested in this tiny, irritating bug, but in retrospect I can't see why anyone would read this. If you did, well ... uh ... sorry about that. ;)

Update 7th February 2011

I was browsing my iPad and noticed that the Marvel app has a UITableView in a popover and it didn't have the issue. I realised they aren't using the setContentSizeForViewInPopover for the RootViewController (it was the height of the device). I am setting the content size for popover to 600 because I didn't want the table view to run all the way to the bottom.

Checked what happens when I remove the call to setContentSizeForViewInPopover from my RootViewController and the issue goes away :).

So to clarify, the UISearchDisplayController only fails to adjust the size of the background view if the UITableViewController has called setContentSizeForViewInPopover.

Permalink - Tags: iPhone,Development