Take the 2-minute tour ×

I'm working with UISearchBar for the first time and can't quite make it do what I want.

When you activate the scope buttons, they cover the first row of the table. The only way to see all of your search results seem to be to hide the scope buttons when editing is finished; in my Googling on this I have seen that suggested.

I want the functionality that Mail has, where the scope buttons stay up as long as there is text in the search box, and you can see the search results change as you change the active scope button. But I can't figure out any way to make this happen without having the first row of the table covered by the scope buttons. You can't just scroll the table view down; the search bar is in the table view's header, so the whole thing scrolls together.

Suggestions appreciated!

Updated after trying Andrew's suggestion below.

One thing I forgot about is that in viewDidAppear I scroll the table view content up, so that the search box is off the top of the screen but can be scrolled down when needed. This is obviously part of my problem. So, in viewDidAppear I have

if (theSearchBar.showsScopeBar != YES) {
    [self.tableView setContentOffset:CGPointMake(0, 44) animated:YES];

In searchBarShouldBeginEditing, I now have:

[self.navigationController setNavigationBarHidden:YES];
[self.tableView setContentOffset:CGPointMake(0, -44) animated:YES];
[UIView beginAnimations:@"searchBarUp" context:nil];
[UIView setAnimationDuration:1.0f];
searchBar.frame = CGRectOffset(searchBar.frame, 0, -44);
[UIView commitAnimations];

This gives the correct result, but when the scope bars come up, there is a gap between the top of the view and the top of the search bar, and the first row is covered. Then the scroll bar (with the scope buttons) slides up into place. This obviously doesn't look very good.

What I would expect the above code to do is:

  • hide the nav bar, which would put the top row of the table right below the status bar

  • scroll the table content back down, which would put the top of the search bar right below the status bar

  • move the search bar up so that there is a 44 pixel gap between the bottom of the search bar, to be filled in by the scope buttons

This does appear to be what happens, except you can see the gap left by the nav bar until the scroll bar moves up to meet it. You would think this could be fixed by hiding the nav bar last, but no... when I tried that I ended up with both the first row of the table covered and a nav bar sized hole between the status and search bars.

Another thing I find very odd is that if I use the above code snippet as is, except with animation:NO on the call to setContentOffset, I get a different result. In this case the first row of the table is not covered, but the search box is above the top of the view and cannot be scrolled down (it won't stay). Only the scope buttons are visible. It doesn't make sense to me that just turning off animation would change the outcome.

Now, you might think that with everything in the right place, displaying the search results would just work. But no. Even though the nav bar is now out of the picture, the search bar still comes up with a large gap above it, and the same adjustments to the table content and the search bar frame are required as above.

I should note that the code in viewWillAppear is only executed once, since we never leave the view, so it's not the case that the table is being readjusted upwards each time.

I would love to understand what's going on, as well as how to fix it, if anyone can help shed some light.

Updated again for clarity - when I say "fix it", what I mean is make it look good without visible gaps when the pieces are moving into place. I don't even necessarily want it animated; the sliding into position takes too long. But as I mentioned above, turning animation off makes things end up in the wrong place again.

Updated one last time - I got it to look much better by removing the animation block around the line to move the search bar. I guess that introduced a pause before the animation began. It's good enough now, at least for the moment. I'm still accepting Andrew's answer since he steered me in the right direction.

share|improve this question
In a very hacky way, remove and re-add to the table view's header so it knows it's been resized? –  tc. Jun 29 '11 at 1:36

3 Answers 3

up vote 0 down vote accepted

You are using a UISearchDisplayController, right? If not, you should. It will take care of a lot of the work you are trying to do yourself, like hiding the navigation bar.

share|improve this answer
Actually I'm not using one, because this is already a table view - when I read about them, the UISearchDisplayController seemed meant to add a temporary table view to a non-table view controller, for the purpose of displaying search results. I also kept seeing complaints about them being hard to customize, so I just used a UISearchBar. That might have been the wrong choice, I'm obviously new to this, but it's working now. Thanks for the answer! –  janineanne Jun 29 '11 at 22:19
It is very much meant for adding to an existing table view. It will overlay the search results table view on top of your normal table view, and all your table view handling code (UITableViewDelegate and UITableViewDataSource methods) can be used to populate it with only minor code changes, if any at all. It is not any harder to customize than a regular table view. I'm glad you got it working, but in the future, do consider giving the UISearchDisplayController a try...I think it will save you a lot of work in the long run. –  gschandler Jun 29 '11 at 22:30
Note that UISearchDisplayController has been deprecated in iOS 8. It is replaced by UISearchController. –  GenesisST Nov 13 at 20:06

In the case of the Mail.app it looks like they hide the UINavigationBar with something like:

[self.navigationController setNavigationBarHidden:YES animated:YES];

Then using a UIView animation, they increase the size of the searchbar to take up the space that was filled by the navigationbar.

pseudo code:

[UIView beginAnimations:@"foo" context:NULL];
[UIView setAnimationDuration:1.0f];
CGRect newFrame = CGRectMake(0,0,self.view.frame.size.width, mySearchBar.frame.size.height);
mySearchBar.frame = newFrame;
//optionally, you could do something like this instead of setting a new frame
// mySearchBar.frame = CGRectOffset(mySearchBar.frame, 0, -44);
[UIView commitAnimations];

This would all go within the UISearchBarDelegate method

- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar

Then when the user cancels the search,

– searchBarCancelButtonClicked:

You'd reverse the animation, and show the navigationbar again.

share|improve this answer
Looks almost right. Just note that searchBarSearchButtonClicked is a bit off. The search display controller does not reverse the animation then. It only reverses why hiding the results table. –  Moshe Jun 29 '11 at 3:57
We're getting closer, but it doesn't work quite right yet. When I click in the search box, three things happen - the nav bar disappears (good), the scope buttons no longer cover the first row of the table (good), and the search box is now scrolled up off the top of the view (so the scope buttons are now right below the status bar). And, even odder, I can't scroll it back down - it springs back up again when you let it go, so it's no longer possible to use the search bar. I tried just hiding the nav bar, without the offset, but that leaves the buttons over the top row. Very perplexing! –  janineanne Jun 29 '11 at 18:00
This could probably be fixed just by adjusting the y origin of the searchBar. Instead of setting it to 0 which seems like it is going up too high, try setting it to 10 and seeing what happens. Alternatively, you might need to move the whole table down a bit. So something along the lines of myTable.frame = CGRectOffset(myTable.frame, 0, 10); –  Andrew Jun 29 '11 at 18:10
Sorry Andrew, I didn't see your comment until after posting my long update above. I think I sort of covered the same ground, though. I'm now getting things to end up in the right place, but they don't look very good getting there. –  janineanne Jun 29 '11 at 19:26

I have had the same problem. Since I wasn't using UISearchDisplayController( I wanted to avoid using the default search table view). So I rather went for the search bar directly. The problem was now the search bar is embedded under a table view ( you can check it in storyboard) . To fix the problem , you will have to embed a tableview and search bar separately under a UIView.

share|improve this answer

Your Answer


