Layout of UISearchBar in UITableView header messed up after rotation

844 Views Asked by At

I have a UITableView with a search bar inserted programatically into the table's headerView:

override func viewDidLoad() {

    super.viewDidLoad()
    resultSearchController = UISearchController(searchResultsController: nil)
    resultSearchController.searchResultsUpdater = self
    resultSearchController.dimsBackgroundDuringPresentation = false
    resultSearchController.searchBar.delegate = self
    resultSearchController.searchBar.placeholder = "Search Contacts"
    resultSearchController.searchBar.scopeButtonTitles = ["All", "Title1", "Title2", "Title3"]

    tableView.tableHeaderView = resultSearchController.searchBar
    resultSearchController.searchBar.sizeToFit()

    definesPresentationContext = true

    tableView.tableFooterView = UIView(frame: CGRectZero)

}`

The table is set up as a standard UINavigationController-based drill down - selecting a row pushes in a detail view controller.

Everything works perfectly in portrait or landscape, but breaks down after the detail view is popped if is has been rotated while displayed. The exact sequence is:

  • open the table in portrait, filter the results using the search bar, and select one of the results to push in the detail view
  • while in the detail view, rotate into landscape
  • while still in the detail view, rotate back into portrait

When the table view reappears, all the individual elements of the search bar have been "collapsed" on top of each other, and the whole thing overlays the status bar:

collapsed search bar

I've tried various ways of explicitly setting the frame of the search bar in viewDidAppear, as well as removing and replacing it from the header view - but the problem persists.

I've also noticed a similar problem with the Apple sample code from https://developer.apple.com/library/prerelease/ios/samplecode/TableSearch_UISearchController/Introduction/Intro.html :

apple code

Had anyone come up with a workaround for this??

Edited to add:

On further digging, it looks like the problem is that the navigation bar disappears after the rotation - here's before:

nav bar exists

and after:

enter image description here

So, any ideas?

1

There are 1 best solutions below

0
On

After noting that an inactive searchBar doesn't seem to have this problem, I have had success with saving the search bar state when the view disappears and restoring it before the view reappears.

The sample code works fine with the following changes. Save the state:

- (void)viewDidDisappear:(BOOL)animated
{
    if (self.searchController.active && self.searchController.searchBar.text.length > 0) {
        self.savedSearch = self.searchController.searchBar.text;
        [self disableSearch];
    } else if (self.searchController.active) {
        // empty search field - this won't get restored
        [self disableSearch];
    }
    [super viewDidDisappear:animated];
}

- (void)disableSearch
{
    if (self.searchController.isActive) {
        self.searchController.searchBar.text = @"";
        self.searchController.active = NO;
    }
}

And restore:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    if (self.savedSearch) {
        NSLog(@"RESTORED SEARCH");
        self.searchController.searchBar.text = self.savedSearch;
        self.searchController.searchBar.showsCancelButton = YES;
        self.searchController.active = YES;
        self.savedSearch = nil;
    }
}

This seems to work fine whether or not self.searchController.hidesNavigationBarDuringPresentation is set (although if true there is some animation on returning to the view).