3
votes

I am using UISearchController to search for data in my tableview. I am not using table view controller. I would like to hide the navigation bar when my search bar is active therefore I set self.searchController.hidesNavigationBarDuringPresentation = YES; to yes.

However when I do this and want to search, my active search bar covers part of the first cell. the covered part has same height as status bar.

status bar active

I tried other articles and questions similar to this one but nothing helped me to solve it. Then I started to play with the table view header size. I did this

 -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{

  return 20.0f;
}

The result was that when I tapped search bar an started to search problem was not there anymore.

search controller with header size 20

However when the search bar is not active there was a gab between searchbar and first cell

enter image description here

Any ideas how to fix this issue?

Edit: after adding self.automaticallyAdjustsScrollViewInsets = false;

enter image description here

7
Try adding self.automaticallyAdjustsScrollViewInsets = false in viewDidLoadRJiryes
it hid the status bar from the top but the first cell is still covered.beowulf
That's weird, it shouldn't affect the visibility of the status bar.RJiryes

7 Answers

3
votes

This is how I set up the search bar and things in viewDidLoad (copied from some of apple's examples).

It presents the found results in the same view controller as your unfiltered data is shown. It also has its search bar in the table header that is hidden until it is needed.

self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.tableView.tableHeaderView = self.searchController.searchBar;
[self.searchController.searchBar sizeToFit];

// we want to be the delegate for our filtered table so didSelectRowAtIndexPath is called for both tables
self.searchController.delegate = self;
self.searchController.dimsBackgroundDuringPresentation = NO; // default is YES
self.searchController.searchBar.delegate = self; // so we can monitor text changes + others

// Search is now just presenting a view controller. As such, the normal view controller
// presentation semantics apply. Namely, that presentation will walk up the view controller
// hierarchy until it finds the root view controller or one that defines a presentation context.
//
self.definesPresentationContext = YES;  // know where you want UISearchController to be displayed

// Hides search bar initially. When the user pulls down on the list, the search bar is revealed.
[self.tableView setContentOffset:CGPointMake(0, self.searchController.searchBar.frame.size.height)];
6
votes

I managed to resolve this issue by combining RJiryes answer with scroll to top.

-(void)willPresentSearchController:(UISearchController *)searchController{

     [self.contactsTableView setContentInset:UIEdgeInsetsMake(20, 0, 0, 0)];
     [self.contactsTableView setContentOffset:CGPointMake(0.0f, -self.contactsTableView.contentInset.top) animated:YES];
 }

-(void)willDismissSearchController:(UISearchController *)searchController{

     [self.contactsTableView setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)];
}
3
votes

You can add content inset from the top instead of adding a header.

  self.tableView.contentInset = UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0)

and when willDismissSearchController (UISearchController's delegate method) is called, return the insets to 0

  self.tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)

This way, you'll avoid the whitespace when it's not active.

0
votes

Not the best solution but just to workaround.

-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return searchController.isActive ? 20.0f : 0.0f; }

0
votes

I have seen similar behavior. Most probably, your table view controller is not implementing heightForHeaderInSection. Precise height of cell is not known, this leads to number of issues like yours.

0
votes

Reseting tableView.tableHeaderView = searchController.searchBar after the dismissing searchController solved the issue for me.

  public func didDismissSearchController(_ searchController: UISearchController) {
            tableView.tableHeaderView = searchController.searchBar
}

Unfortunately didDismissSearchController doesn't get called if you select a result and go back to parent viewController. In this case you need reset the searchBar.frame back to origin position:

if let frame = tableView.tableHeaderView?.frame {
    searchController.searchBar.frame = frame
}
-1
votes

I have the same trouble. And research didn't answer. My decision:

1) I used UITableviewController with SearchController and when I taped on the field I had this UI trouble: Extra blank space between searchBar and tableview The guys noted that you need to use the searchController with UIViewcontroller and tableView separately. So I did

2) There was this problem. It is solved as follows:

 let searchController = UISearchController(searchResultsController: nil)
var tableView:UITableView!

override func viewDidLoad() {
    super.viewDidLoad()

    loadData()
    setupTableView()
    setupSearchController()
}

private func setupTableView(){

    tableView = UITableView(frame: CGRect.zero, style: .plain)

    **//next 2 very important line of code**

    tableView.autoresizingMask = UIViewAutoresizing()
    tableView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(tableView)

    tableView.dataSource = self
    tableView.delegate = self
    tableView.register(LetterBrandCell.self, forCellReuseIdentifier: "brandCell")
    tableView.tableFooterView = UIView()
    addConstraints()
}

In the method of adding constraints, it is important to be attached to top & bottomLayoutGuides, not just to view:

private func addConstraints(){

    NSLayoutConstraint(item: tableView,
                       attribute: .top,
                       relatedBy: .equal,
                       toItem: topLayoutGuide,
                       attribute: .bottom,
                       multiplier: 1,
                       constant: 0).isActive = true

    NSLayoutConstraint(item: tableView,
                       attribute: .bottom,
                       relatedBy: .equal,
                       toItem: bottomLayoutGuide,
                       attribute: .top,
                       multiplier: 1,
                       constant: 0).isActive = true
    NSLayoutConstraint(item: view,
                       attribute: .leading,
                       relatedBy: .equal,
                       toItem: tableView,
                       attribute: .leading,
                       multiplier: 1,
                       constant: 0).isActive = true
    NSLayoutConstraint(item: view,
                       attribute: .trailing,
                       relatedBy: .equal,
                       toItem: tableView,
                       attribute: .trailing,
                       multiplier: 1,
                       constant: 0).isActive = true

}