66

I'm updating my app for iOS 7, and I'm in the process of adjusting all my views to account for the new transparent status bar (my app will still use opaque navigation bars).

It was relatively easy to adjust for the status bar in every view, except one major problem I'm having with a UISearchBar connected to a UISearchDisplayController in one of my view controllers.

The search bar seems to display normally, as shown below:

Search Bar

The problem is, as soon as I begin searching, the navigation bar disappears (as it should), but everything else also moves up to overlap the status bar:

Broken Search Bar

This doesn't appear to be working as intended, since the darkening of the screen happens 20 pixels below the search bar, where the search bar should end.

Is there a built in solution for this in iOS 7? I'd rather not have to manually adjust the frame for every view each time the user begins and ends searching.

Thanks!

Community
  • 1
  • 1
desmondhume
  • 903
  • 1
  • 7
  • 9
  • I would like to point out that I have a search display controller and search bar in another view, attached to a UITableViewController, which transitions fine. Maybe that has something to do with the problem? – desmondhume Sep 20 '13 at 23:15
  • i have the same problem, any update for this topic? – David L Sep 23 '13 at 04:27
  • I have the same setup and the same issue. – Hackmodford Sep 23 '13 at 13:08
  • I think it is related to being the first view in a navigationcontroller hierarchy. For instance this only happens in the view associated with a tab on the tabbarcontroller. – Hackmodford Sep 23 '13 at 13:29

12 Answers12

88

Putting the following line in the viewDidLoad fixed it for me:

self.edgesForExtendedLayout = UIRectEdgeNone;
Deddiekoel
  • 1,939
  • 3
  • 17
  • 25
  • 20
    If you're going this route, `self.edgesForExtendedLayout = UIRectEdgeLeft | UIRectEdgeBottom | UIRectEdgeRight;` is probably a better and more general solution assuming your search bar is at the top of the screen. (This will preserve the extended layout for other edges, which is important for things like toolbars with blurring at the bottom of the screen.) – smileyborg Sep 26 '13 at 05:45
  • 4
    just check [self respondsToSelector:@selector(edgesForExtendedLayout)] to prevent a crash on < iOS 7. – richy Oct 15 '13 at 06:29
  • @richy Didn't get your point. I'm getting error if same code is opened in Xcode 4.x. – Jayprakash Dubey Nov 27 '13 at 14:08
  • 1
    Jayprakash XCode 4.x only supports iOS6.x and below so you will need to do `if ([self respondsToSelector:@selector(edgesForExtendedLayout)]){self.edgesForExtendedLayout = UIRectEdgeNone;}` – richy Nov 29 '13 at 06:31
  • 1
    This didn't work for me until I saw that view controllers have a reference for SearchDisplayControllers. Once I linked this in IB, it worked! – Megasaur Dec 14 '13 at 14:31
  • It should, I've tested it in a UISplitView. – Deddiekoel Dec 30 '13 at 10:10
  • self.edgesForExtendedLayout = UIRectEdgeNone; work for me – Vijay Masal Oct 25 '16 at 12:10
21

Thank you hodade for leading me on the right track! Your solution worked, except it only moved the search bar's frame, leaving my other subviews in the wrong spot. The only thing I changed was to move all the subviews in my view, as well as animate it.

Thanks!

-(void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        CGRect statusBarFrame =  [[UIApplication sharedApplication] statusBarFrame];
        [UIView animateWithDuration:0.25 animations:^{
            for (UIView *subview in self.view.subviews)
                subview.transform = CGAffineTransformMakeTranslation(0, statusBarFrame.size.height);
        }];
    }
}

-(void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller {
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        [UIView animateWithDuration:0.25 animations:^{
            for (UIView *subview in self.view.subviews)
                subview.transform = CGAffineTransformIdentity;
        }];
    }
}
desmondhume
  • 903
  • 1
  • 7
  • 9
  • 1
    This and hodade's answer did not help me. It still automatically moves the searchbar up. – Hackmodford Sep 25 '13 at 13:35
  • 1
    Upon further review this seems like a timing issue. Using DidBeginSearch will make it animate under the status bar then go back down some more... – Hackmodford Sep 25 '13 at 13:39
  • With out adding anything its working for me in iOS7 in some cases..but in one case its not working..what is the reason?why we need to write the above code? – Sandeep Oct 09 '13 at 14:22
13

You're may using no translucent navigation bar? If so, this will solve it.

- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
    self.navigationController.navigationBar.translucent = YES;
}

- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller {
    self.navigationController.navigationBar.translucent = NO;
}
tachiba
  • 139
  • 1
  • 3
7

Just place following code in -(void) ViewDidLoad. It will work for iOS 7 and later version

if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
    self.edgesForExtendedLayout = UIRectEdgeNone;
}

UPDATE:

if(SYSTEM_VERSION_GREATER_THAN(@"6.1")) {
    self.edgesForExtendedLayout = UIRectEdgeNone;
}
MD SHAHIDUL ISLAM
  • 14,325
  • 6
  • 82
  • 89
  • Thanks a lot @Salim! This solution works for a UISearchBar embedded in a UIViewController that is opened as a popup on iPad/iPhone6+. – AlBirdie Nov 13 '14 at 17:32
6

This seems to describe the problem I was having; hopefully it will help someone in my former positon.

  1. Subclass your SearchDisplayController that's been added to your UIViewController/UITablewViewController,

  2. Add something like this to its implementation:

     - (void)setActive:(BOOL)visible animated:(BOOL)animated
    {
        [super setActive:visible animated:animated];
    
        [self.searchContentsController.navigationController setNavigationBarHidden: NO animated: NO];
    
        CGRect frame = self.searchResultsTableView.frame;
        frame.origin.y = CGRectGetHeight(self.searchContentsController.navigationController.navigationBar.frame);
    
        frame.size.height = CGRectGetHeight(frame) - CGRectGetMinY(frame);
    
        self.searchResultsTableView.frame = frame;
    
        frame = self.searchBar.frame;
        self.searchBar.frame = frame;
    
        [self.searchContentsController.view insertSubview:self.searchBar aboveSubview:self.searchResultsTableView];
    
    }
    
Morkrom
  • 578
  • 7
  • 26
6

I did below code to solve the problem.

    - (void) viewDidLayoutSubviews
{
         if(floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1)
        {
            CGRect viewBounds = self.view.bounds;
            CGFloat topBarOffset = self.topLayoutGuide.length;
            viewBounds.origin.y = topBarOffset * -1;
            self.view.bounds = viewBounds;
        }
}
Sabareesh
  • 3,585
  • 2
  • 24
  • 42
  • I suspect, this should go into a UISearchDisplayController subclass? This does not have a view property. – osxdirk Apr 01 '14 at 16:02
5

I think maybe add this to viewDidLoad will help:

if([self respondsToSelector:@selector(setEdgesForExtendedLayout:)])
{
    self.edgesForExtendedLayout = UIRectEdgeNone;

}
EVA
  • 375
  • 1
  • 6
  • 18
3

just add

self.definesPresentationContext = YES;

you can read more from here: UISearchController and definesPresentationContext

and from Apple documentation: UISearchController documentation

Note: UISearchDispalyController is deprecated in iOS7, use UISearchController instead in iOS8, method above use UISearchController

2

In my case, the views below the search bar were at their right place, only the search bar was overlapping the status bar. In this case, this peace of code works fine:

- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {        
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
        CGRect statusBarFrame =  [[UIApplication sharedApplication] statusBarFrame];
        CGRect frame = self.searchBar.frame;
        frame.origin.y += statusBarFrame.size.height;
        self.searchBar.frame = frame;
    }
}

- (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller {
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
        CGRect statusBarFrame =  [[UIApplication sharedApplication] statusBarFrame];
        CGRect frame = self.searchBar.frame;
        frame.origin.y -= statusBarFrame.size.height;
        self.searchBar.frame = frame;
    }
}

Hope it will be useful to others

Aurelien Porte
  • 2,692
  • 27
  • 32
0
-(void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        CGRect statusBarFrame =  [[UIApplication sharedApplication] statusBarFrame];
        CGRect frame = controller.searchBar.frame;
        frame.origin.y += statusBarFrame.size.height;
        controller.searchBar.frame = frame;
    }
}

-(void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller {
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        CGRect statusBarFrame =  [[UIApplication sharedApplication] statusBarFrame];
        CGRect frame = controller.searchBar.frame;
        frame.origin.y -= statusBarFrame.size.height;
        controller.searchBar.frame = frame;
    }
}
hodade
  • 9
  • 1
0

The above answers only work if you have your navigation bar unhidden. If you have your navigation bar hidden try this:

-(void)viewDidAppear:(BOOL)animated{
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
    CGRect statusBarFrame =  [[UIApplication sharedApplication] statusBarFrame];
    [self.tableView setFrame:CGRectMake(self.tableView.frame.origin.x, self.tableView.frame.origin.y+statusBarFrame.size.height, self.tableView.frame.size.width, self.tableView.frame.size.height)];

    }
}

Based on this post: UISearchBar overlaps status bar in iOS

Community
  • 1
  • 1
Andrew Schreiber
  • 14,344
  • 6
  • 46
  • 53
0

Subclass your SearchDisplayController that's been added to your UIViewController/UITablewViewController and add this to its implementation -

- (void)setActive:(BOOL)visible animated:(BOOL)animated
{
    if(self.active == visible) return;
    [self.searchContentsController.navigationController setNavigationBarHidden:YES animated:NO];
    [super setActive:visible animated:animated];
    [self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
    if (visible) {
        [self.searchBar becomeFirstResponder];
    } else {
        [self.searchBar resignFirstResponder];
    }
}
Rahul Mane
  • 1,005
  • 18
  • 33
G.T.
  • 1