UISearchController: searchBar and scopeBar overlap on first touch event
Asked Answered
B

3

4

I'm trying to implement a simple search bar using Apple's latest UISearchController. However I can't seem to get it to work correctly if I use the search bar's scope bar to get a filter choice.

The scope bar always shows which I could live with at startup scope bar always shows

but on the very first touch event the search bar and scope bar overlap. Search bar and scopebar collapse

I used Apple's TableView sample code app but it didn't change anything.

- (void)viewDidLoad {
[super viewDidLoad];

_resultsTableController = [[APLResultsTableController alloc] init];
_searchController = [[UISearchController alloc] initWithSearchResultsController:self.resultsTableController];
self.searchController.searchResultsUpdater = self;
[self.searchController.searchBar sizeToFit];
self.searchController.searchBar.showsScopeBar = YES;
[self.searchController.searchBar setScopeButtonTitles:@[@"First",@"Second"]];
self.tableView.tableHeaderView = self.searchController.searchBar;

// we want to be the delegate for our filtered table so didSelectRowAtIndexPath is called for both tables
self.resultsTableController.tableView.delegate = self;
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, 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

}

I implemented the search bar's delegate methods as well but it just switches the timing of the overlap.

Has anyone been able to implement a search bar using iOS 8s UISearchController and using the searchBar's scope bar?

Thanks in advance

Blowgun answered 15/7, 2015 at 7:52 Comment(2)
Did you find a solution for this?Sextain
Same behavior for me when switching from portrait to landscape, and back to portrait. If the search is active (ie : seachBar is firstResponder) during this process, then I get the same result : scopeButtons visibles behind the searchBar.... After the UISearchDisplayController, the UISearchController... as buggy as its predecessor, well done Apple ^^Herve
T
2

I just spent three days working on this same issue going through all of the posts I could find and just finally found the solution on the Apple Dev forum so thought I would post an update to help the next person that encounters this issue.

The resolution is to make sure that the showsScopeBar property on the search bar belonging to a UISearchController is set to false, i.e. UISearchController.searchBar.showsScopeBar = false in Swift.

The issue seems to be that Apple's design intent is for the showsScopeBar property to be used with standalone search bars not search bars controlled by a UISearchController. Unfortunately this is not called out in the class documentation. Bad design decision in my opinion but it is what it is.

The discussion is in the following thread https://devforums.apple.com/thread/235803 (dead link as of 2018-01-26).

Best of luck.

Tong answered 4/7, 2016 at 5:40 Comment(0)
K
1

This appears to be a known defect. There are several radr entries such as http://www.openradar.me/20702394 that refer to similar issues and a workaround by using sizeToFit()

The workaround they suggest works, but only when it was applied within viewDidLayoutSubviews. i.e. after all of the views were laid out.

override func viewDidLayoutSubviews() {
    self.searchController.searchBar.sizeToFit()
}
Kahl answered 12/9, 2015 at 3:53 Comment(1)
Sadly this didn't work for me. However what worked for me in the end was using the sizeToFit in -(void)didPresentSearchController:(UISearchController *)searchController{ [searchController.searchBar sizeToFit]; }Blowgun
V
0

Update for swift 3:

searchController.searchBar.showsScopeBar = false

Update for swift 4:

It seems that in swift 4 and ios 11 the search bar got changed. With the method showed above the scope bar will be inside the search bar in some cases.

if #available(iOS 11.0, *) {
        navigationItem.searchController = searchController
        navigationItem.hidesSearchBarWhenScrolling = false
    } else {
        tableView.tableHeaderView = searchController.searchBar
    }

This fixed it for me. I use the the form shown above if ios 10 is available. If ios 11 is available i change my technic and set the navigation view controller to the search controller. You will notice it looks exactly as on ios 10

Voracity answered 30/8, 2017 at 21:55 Comment(1)
The showsScopeBar attribute is only releated to custom search bars. If you specefy your scope button titles and set the schowsScopeBar to false everything should work, because otherwise you are creating to scopeBars. One automatically created by your SearchBarController and another by setting .showsScopeBar to true. If you would set it to false the scope bar will only show up when you actually search something and it would no overlap with the searchBarVoracity

© 2022 - 2024 — McMap. All rights reserved.