UITableView with UISearchController go under navbar when enter in a result view and come back
Asked Answered
I

4

16

I have a UITableView with a UISearchController search bar in the UINavigationBar, all works perfectly, but when I push a result of the searched results of the UISearchController, and I come back the UITableView is under the NavBar, this is how I initialize the UISearchController:

        self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
        self.searchController.delegate = self;
        self.searchController.searchResultsUpdater = self;

        self.searchController.searchBar.delegate = self;
        self.searchController.dimsBackgroundDuringPresentation = NO;
        self.searchController.hidesNavigationBarDuringPresentation = NO;
        self.searchController.searchBar.placeholder = NSLocalizedString(@"Local Search", @"");
        self.searchController.searchBar.frame = CGRectMake(0, -5, [UIScreen mainScreen].bounds.size.width, 44);


        ctrl = [[UIView alloc] initWithFrame:CGRectMake(0, 0,[UIScreen mainScreen].bounds.size.width, 44)];
        ctrl.backgroundColor = [UIColor clearColor];
        ctrl.autoresizingMask = UIViewAutoresizingFlexibleWidth;
        [ctrl addSubview:self.searchController.searchBar];
        self.navigationItem.titleView = ctrl;
        self.definesPresentationContext = YES;

The search bar is displayed perfectly in the UINavigationBar, then when I search something and I push the view controller of one results like this:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
    DetailListController *detailList = [[DetailListController alloc] init];
    [self.navigationController pushViewController:detailList animated:YES];
}

when I come back to the UITableView doing this:

[self.navigationController popViewControllerAnimated:YES];

the UITableView is under the UINavigationBar, how I can fix this?

thanks

Ishtar answered 8/10, 2015 at 9:15 Comment(0)
E
15

I had exactly the same problem, setting extendedLayoutIncludesOpaqueBars to YES/true in view controller, that presents search controller, seems to fix it.

self.extendedLayoutIncludesOpaqueBars = YES

As a word of caution: setting this property changes value of scroll view's vertical content offset.

Elizabetelizabeth answered 4/12, 2015 at 23:35 Comment(0)
H
11

This is an extremely frustrating bug in UIKit. What appears to be happening is that the presenting view controller's top layout guide get reset to 0, meaning it is now underneath the nav bar. The layout guide is a read only property, so you can't fix it by editing directly. However, I did come up with a hack to get it to reset to the correct value. Add this to your UISearchControllerDelegate:

- (void)didDismissSearchController:(UISearchController *)searchController
{
    UINavigationController *nav = self.navController; // you muse save this earlier

    // force to layout guide to reset by pushing a dummy controller and popping it right back
    [nav pushViewController:[UIViewController new] animated:NO];
    [nav popViewControllerAnimated:NO];
}
Hellman answered 25/7, 2016 at 18:0 Comment(2)
Did anyone open an open radar for this?Reverberatory
Thanks, is not there any other way of forcing the layout guide to reset programmatically?Discrimination
C
1

I have used UISearchController for years but today is the first time I am facing this issue I used to set edgesForExtendedLayout = [] and extendedLayoutIncludesOpaqueBars = true and everything is fine

but today It is not, I needed to reverse it to edgesForExtendedLayout = .all it may be useful to you too!

Capernaum answered 10/7, 2020 at 19:10 Comment(0)
S
0

Ran into this issue today and resolved using a reference to the result view controller's safeAreaLayoutGuide

After refreshing your result table's contents, you can then call this method:

// NOTE: this method is used to fix a known UIKit bug where search results that do not have a content
    // size that fills the view will be placed underneath the navigation bar when displayed. this hack
    // fixes this issue by resetting the contentInset based on the content size.
    private func adjustContentInsetForContentSize() {
        if collectionView.contentSize.height > view.frame.height {
            collectionView.contentInset = UIEdgeInsets.zero
        } else {
            collectionView.contentInset = UIEdgeInsets(top: view.safeAreaLayoutGuide.layoutFrame.origin.y, left: 0, bottom: 0, right: 0)
        }
    }

Essentially the issue is caused by having a result view that has a contentSize height that is smaller than the viewable region for the view. The results render find when the contentSize.height > view.frame.height, so this hack will force the content insets to properly respect the safe area layout guide.

Slaby answered 18/12, 2019 at 0:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.