I have a UITableViewController in Objective-C that is supposed to launch without a search bar, but a UISearchBar is added on a certain button press. Whenever the search bar is added, I also add a tableHeaderView to the UITable that works in conjunction with the search bar. It is all working well, except in iOS 13 where this happens:
When the tableHeaderView (which was initially nil) is set to the appropriate view, that view appears and covers the top line of the table under it. If there are 3 items in the table, we only see 2 of them. If I try to scroll down the table, I can briefly expose that top table entry, but I cannot tap on it because it goes right back under the tableHeaderView when I let go of the scroll. But here is the strange thing: Under these conditions, with the tableHeaderView covering the top table entry, if I rotate between landscape and portrait, the re-layout that happens fixes the layout. After the rotation, all the items in the table are visible. Somehow the table has learned how to lay itself out to avoid the tableHeaderView. But if I cancel the search bar (and hence the tableHeaderView by setting it to nil) and then call for the search bar again, the problem comes back.
So what I would like to do is to force whatever recalculations were made in the rotation whenever the search bar is called for. Is there any way to force a view unload and view reload at such times? (or whatever happens in a rotation.)
Here is how the search bar is launched:
- (void)didPressSearch {
if(self.searchController.isActive == NO)
self.tableView.tableHeaderView = self.searchController.searchBar;
[self.searchController.searchBar becomeFirstResponder];
}
Here is how the search bar is cancelled:
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
self.tableView.tableHeaderView = nil;
}
This solution is not perfect, but after trying everything I could think of and everything I could find on-line, this is the closest I could come to the desired behavior: (for simpliciy, I am showing only what the code is when running under iOS 13+)
- (void)viewDidLoad
{
[super viewDidLoad];
UISearchController *sc = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController = sc;
sc.searchResultsUpdater = self;
UISearchBar *sb = sc.searchBar;
sb.delegate = self;
sb.scopeButtonTitles = @[@"Starting with...", @"Containing..."];
sc.dimsBackgroundDuringPresentation = NO;
self.navigationItem.searchController = sc;
self.definesPresentationContext = YES;
[sb sizeToFit];
}
- (void)didPressSearch {
[self.searchController.searchBar becomeFirstResponder];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
//..nothing needed
}
With this code the operation is acceptable, but the search bar is always shown (albeit without the scope buttons). The scope buttons appear when the search bar becomes the first responder and they disappear when the Cancel button is pressed. But it would be nice if the whole search bar would disappear when the Cancel button is pressed. I am marking this thread closed because the solution is acceptable, even if it is not exactly what I wanted.