Using UISearchController with UISearchBar in tableHeaderView in iOS11
Asked Answered
P

0

6

Has anyone successfully retained a UISearchBar in a tableHeaderView of a UITableView in ios11? Problems usually arise with iPhone X in landscape:

enter image description here

Apple recommends using the new searchController property:

if (@available(iOS 11.0, *)) {
    self.navigationItem.searchController = self.searchController;
    self.navigationItem.hidesSearchBarWhenScrolling = NO;
} else {
    self.tableView.tableHeaderView = self.searchController.searchBar;
}

However this doesn't always work. Here is an example with code:

iOS11 UISearchBar missing in UINavigationBar when embedded in UISplitViewController

So trying to keep the searchBar in tableHeaderView - a practical first step is to apply the appropriate auto layout constraints:

if (@available(iOS 11.0, *)) {
    UILayoutGuide *guide = self.tableView.safeAreaLayoutGuide;
    searchBar.translatesAutoresizingMaskIntoConstraints = NO;
    [searchBar.leftAnchor constraintEqualToAnchor:guide.leftAnchor].active = YES;
    [searchBar.rightAnchor constraintEqualToAnchor:guide.rightAnchor].active = YES;
}

The searchBar is then correctly sized when displayed:

enter image description here

However the problem arises when the UISearchBar is activated:

enter image description here

This seems to be an old problem. There are numerous stackoverflow questions and answers relating to issues like this. In this case, on inspection of the view hierarchy, it appears the width of the UISearchBar is set incorrectly. So this can be corrected:

- (void)didPresentSearchController:(UISearchController *)searchController NS_AVAILABLE_IOS(11_0)
{
    if (@available(iOS 11.0, *)) {
        CGRect frame = self.searchController.searchBar.frame;
        frame.size.width = [self safeWidthAvailable];
        self.searchController.searchBar.frame = frame;
    }
}

- (CGFloat)safeWidthAvailable
{
    CGRect frame = ((AppDelegate *)MyApplication.sharedApplication.delegate).window.frame;
    CGFloat width = frame.size.width;
     if (@available(iOS 11.0, *)) {
       UIEdgeInsets insets = ((AppDelegate *)MyApplication.sharedApplication.delegate).window.safeAreaInsets;
       width -= insets.left;
       width -= insets.right;
    }
    return width;
}

So this works:

enter image description here

Until you rotate with UISearchController active:

enter image description here

So again UISearchController has misplaced UISearchBar.

Why is this so hard?

One solution is to save the search, disable UISearchController after a rotation, and re-enable it with the saved search. This works, but it shouldn't need to be so complicated.

Any suggestions?

Pinkie answered 13/10, 2017 at 19:51 Comment(1)
Maybe you can consider my answer here. https://mcmap.net/q/1919200/-limit-the-height-of-uisearchbar-in-ios-11Odo

© 2022 - 2024 — McMap. All rights reserved.