Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UITableView contentSize wrong when using UISearchBar

UITableView is reporting a bigger contentSize than expected when using a UISearchBar. With zero cells, the expected content height would be zero. Instead, the following code outputs 612 in iPhone 4-inch running iOS 7.

@implementation HPViewController {
    UITableView *_tableView;
    UISearchBar *_searchBar;
    UISearchDisplayController *_searchController;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    _tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
    _tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    [self.view addSubview:_tableView];

    _searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];

    _searchController = [[UISearchDisplayController alloc] initWithSearchBar:_searchBar contentsController:self];
    _searchController.delegate = self;
    _searchController.searchResultsDataSource = self;
    _tableView.tableHeaderView = _searchBar;
}

- (void)viewDidLayoutSubviews
{
    CGSize contentSize = _tableView.contentSize;
    NSLog(@"%f", contentSize.height); // 612.000000
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 0; }
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { return nil; };

@end

Commenting the line that sets the header view makes the code output 0, as expected.

Also, if I assign an empty UIView as the header, the contentSize will be correct and match the height of the header. The problem only happens with UISearchBar.

Is there any way around this? Am I doing something wrong?

like image 509
hpique Avatar asked Jan 21 '14 14:01

hpique


2 Answers

Placing the UISearchBar inside a container UIView mostly fixes the problem.

- (void)viewDidLoad
{
    [super viewDidLoad];
    _tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
    _tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    [self.view addSubview:_tableView];

    UIView *searchBarContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
    _searchBar = [[UISearchBar alloc] initWithFrame:searchBarContainer.bounds];
    [searchBarContainer addSubview:_searchBar];

    _searchController = [[UISearchDisplayController alloc] initWithSearchBar:_searchBar contentsController:self];
    _searchController.delegate = self;
    _searchController.searchResultsDataSource = self;
    _tableView.tableHeaderView = searchBarContainer;
}

Unfortunately the UISearchBar glitches in some scenarios that I couldn't isolate yet. I opted to calculate the contentSize manually by adding the height of all cells.

like image 75
hpique Avatar answered Sep 20 '22 09:09

hpique


Starting from iOS11, UITableView uses estimate row/header/footer height to calculate initial contentSize by default. In fact, if you tap on the search bar and dismiss the keyboard, content size will have the correct value.

To fix this behavior, set estimate row, header and footer height to 0 in IB instead of Automatic:

enter image description here

or just do it programmatically:

self.tableView.estimatedRowHeight = 0;
self.tableView.estimatedSectionHeaderHeight = 0;
self.tableView.estimatedSectionFooterHeight = 0;
like image 34
Donnit Avatar answered Sep 21 '22 09:09

Donnit