Reputation: 556
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.
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.
However when the search bar is not active there was a gab between searchbar and first cell
Any ideas how to fix this issue?
Edit: after adding self.automaticallyAdjustsScrollViewInsets = false;
Upvotes: 3
Views: 6042
Reputation: 6103
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)];
Upvotes: 3
Reputation: 2519
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
}
Upvotes: 0
Reputation: 21
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
}
Upvotes: -1
Reputation: 556
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)];
}
Upvotes: 6
Reputation: 6103
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.
Upvotes: 0
Reputation: 61
Not the best solution but just to workaround.
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return searchController.isActive ? 20.0f : 0.0f;
}
Upvotes: 0
Reputation: 961
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.
Upvotes: 3