iOS 11 search bar jumping to top of screen
Asked Answered
M

5

13

I've got a UITableView in which I set its header to be a search bar.

tableView.tableHeaderView = searchController.searchBar

Everything works according to plan until you click it and it seemingly detaches from the tableView and jumps to the top of the screen. The tableView rows stay in place. Any reason it would do that in iOS 11 and not iOS 10?

Moeller answered 21/8, 2017 at 13:54 Comment(1)
Not enough info to reproduce. Setting the table view's table header view to the search controller's search bar still works fine for me in iOS 11.Sedition
S
15

It is encouraged to apply the new way to show search bar/search controller on iOS 11. Here is what I have done:

    if #available(iOS 11.0, *) {
        navigationItem.searchController = searchController
    } else {
        tableView.tableHeaderView = searchController.searchBar
    }
Shyamal answered 28/9, 2017 at 4:10 Comment(1)
Thanks @Simon Wang! Been looking for this solution! For those who'd want the searchbar to be always displayed, add: navigationItem.hidesSearchBarWhenScrolling = NO;Chil
R
4

My first post on SO, i hope i am doing this right.

I had the exact same problem and really struggled with finding a solution. But now i have managed to fix it by subclassing UISearchController.

This subclass has two properties:

var customDelegate : CustomSearchControllerDelegate!
var searchBarWithCustomSize : UISearchBar!

So instead of using the searchBar of UISearchController i can now use the new property searchBarWithCustomSize from my custom searchController, like this:

tableView.tableHeaderView = customSearchController.searchBarWithCustomSize

This makes the searchbar behave correctly when active. You also have more freedom with this searchBarWithCustomSize, for example you can change its frame if needed and so on.

In my implementation i need the delegate to know when the searchbar textfield has been changed but i guess the usage of a delegate is dependent on your situation.

Rumilly answered 21/9, 2017 at 8:46 Comment(2)
Could you post code of your entire class for us? Thanks.Shiva
If you show some code or workflow for code then it will be super helpful.Clientage
I
2

I had the exact same issue - weird jumping behaviour of the UISearchBar on iOS11, where on iOS10 everything is fine.

Regarding the advice by Simon Wang above - the problem I had there is that I am not defining my UISearchBar inside a UIViewController, I am instead inside another UITableViewCell - so therefore I don't have access to the navigationItem and can't present my search bar that way.

Anyway, after much trial and error, the only way I could get things working was to scrape the UISearchController and related delegates altogether.

Instead I define a UISearchBar inside Interface Builder, and define its layout constraints as appropriate. I then make its parent class conform to UISearchBarDelegate and do searchBar.delegate = self

I then add a bunch of delegate methods to catch content changes to the search bar, and update my table results accordingly:

func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {  
   filterContentForSearchText(self.searchBar.text!)
}

func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
   filterContentForSearchText(self.searchBar.text!)
   self.searchBar.resignFirstResponder()
}

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
   filterContentForSearchText(self.searchBar.text!)
}

And life is good again. Hope this helps!

Infatuated answered 8/10, 2017 at 21:31 Comment(1)
I know this is several years old, but this solution worked out great for me since I don't have a navigation bar. Thanks for sharing!Nephrolith
C
0

Try this:

if (@available(iOS 11, *)){
    [searchVC.searchBar addObserver:self forKeyPath:@"frame" options: NSKeyValueObservingOptionNew context:nil];
}else{
    [view addSubview:searchVC.searchBar];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    CGRect rect = [change[@"new"] CGRectValue];
    if (rect.origin.y == 14) {
        CGRect temp = rect;
        temp.origin.y = 20;
        [self.searchVC.searchBar setValue:@(temp) forKey:@"frame"];
    }else if (rect.size.height == 56){
        CGRect temp = rect;
        temp.size.height = 50;
        [self.searchVC.searchBar setValue:@(temp) forKey:@"frame"];
    }
}
Chilon answered 14/10, 2017 at 3:17 Comment(0)
E
0

Try this.

if #available(iOS 11.0, *) {
    searchBar.heightAnchor.constraint(equalToConstant: 44).isActive = true
}
Exsect answered 29/10, 2017 at 14:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.