UISearchBarController iOS 11 issue - SearchBar and scope buttons overlap
Asked Answered
F

7

13

Referred here and here. No answer in first link. In the second link, though the answer is not accepted, but the link to apple developer forum gives error.

Before iOS 11 :

enter image description here

iOS 11 :

enter image description here

Note : Same device same code.
Also, this would mean, all apps using this feature have to be republished ?

Farias answered 22/9, 2017 at 11:55 Comment(10)
see this once #31425040Mona
@Mona This link is attached by NitishDemantoid
Try with self.definesPresentationContext = true write this line in your viewDIdloadInspissate
@TofaaniKaanudo : Already thereFarias
is your searchbar in your navigation bar ? or there is no navigation bar in that viewcontroller ?Discrimination
@Lion : There is a navigation bar but the searcher is not in it. It is tableview's header.Farias
I encounter the same issue. Worked fine on iOS 10. To mee it seams UISearchController is just completely broken in iOS 11.0.Bracci
The example on this site displays the same issue: raywenderlich.com/157864/…. Searching on Twitter reveals more victims of this bug, Apple really dropped the ball on this one.Bracci
Have you tried this: https://mcmap.net/q/907266/-uisearchcontroller-searchbar-frame-only-resizes-on-first-click ?Vain
have you tried this self.navigationController?.navigationBar.prefersLargeTitles = true; for iOS 11?Bootlace
M
7

Adding these lines fixed it for me:

override func viewDidLayoutSubviews() {
    self.searchController.searchBar.sizeToFit()
}
Mb answered 19/10, 2017 at 19:36 Comment(2)
Fixed for me too. I just added SearchController to the tableView without conditionally checking for iOS 11. It has to be linked against iOS 11 SDK though, this method is not working when linked against iOS 10 SDK.Convexoconvex
For iOS 11, the top ranked answer here: #45783169 is the way.Fitly
S
2

I can get the initial appearance to display correctly in iOS11 using the following code (as per greg's answer):

[self.searchController.searchBar sizeToFit];

if (@available(iOS 11.0, *)) {
    self.navigationItem.searchController = self.searchController;
    self.navigationItem.hidesSearchBarWhenScrolling = NO;
} else {
    // Fallback on earlier versions
    self.tableView.tableHeaderView = self.searchController.searchBar;
}

However, if the app is backgrounded then restored while the search bar was active, the appearance would end up overlapped as shown in Nitish's second screenshot above.

I was able to fix that with the following workaround:

[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
    self.searchController.searchBar.showsScopeBar = NO;
    [self.searchController.searchBar sizeToFit];
    self.searchController.searchBar.showsScopeBar = YES;
    [self.searchController.searchBar sizeToFit];
}];

(I'm still working on how to workaround the layout issues following an interface orientation change while the search bar is active - that still ends up overlapped.)

Scullion answered 26/11, 2017 at 22:41 Comment(0)
W
1

In the radar that Ray Wenderlich filed, @benck posted this answer from WWDC, which, if I'm not mistaken, hasn't been posted yet.

Wertz answered 2/10, 2017 at 19:24 Comment(0)
R
1

Per your comments, your UISearchController's UISearchBar has been assigned to your UITableView's tableHeaderView. In iOS 11, you should instead be assigning your UISearchController to the searchController property of your view's navigationItem. You no longer need to assign the UISearchBar anywhere. See Apple's documentation on this new property.

Recognizee answered 3/10, 2017 at 22:53 Comment(0)
O
1

I met the same issue on my app, my solution is in iOS 11, using apple suggested new way for searchBar which is in navigationItem, otherwise, using the old way. My code in viewDidLoad() as below:

if #available(iOS 11.0, *) {
    navigationController?.navigationBar.prefersLargeTitles = false
    navigationItem.searchController = searchController
    navigationItem.hidesSearchBarWhenScrolling = false
    searchViewHeight.constant = 0
} else {
    searchView.addSubview(searchController.searchBar)
}

I have two IBOutlets: searchView and searchViewHeight:

@IBOutlet var searchView: UIView!
@IBOutlet var searchViewHeight: NSLayoutConstraint! // new added for iOS 11

Before iOS 11, my viewController's hierarchy as below:

My searchView before iOS 11

I have a searchView which height is 44 to contains my searchController's searchBar view. It's under navigation bar.

In iOS 11, I add a new IBOutlet for searchView's height constraint, and set its constant to 0, hide this container view. And add searchController as a part of navigation item.

See apple's document: https://developer.apple.com/documentation/uikit/uinavigationitem/2897305-searchcontroller

One more thing is under iOS 11, the searchBar's textField background color is little darker than navigation bar color by default. For consistency, you can change it to white, the below code will work both for iOS11 and its prior:

if let textField = searchController.searchBar.value(forKey: "searchField") as? UITextField {
    if let backgroundView = textField.subviews.first {

        // Search bar textField background color
        backgroundView.backgroundColor = UIColor.white

        // Search bar textField rounded corner
        backgroundView.layer.cornerRadius = 10
        backgroundView.clipsToBounds = true
    }
}
Olcott answered 15/10, 2017 at 6:40 Comment(0)
R
0

I think that the solution is to add the Search Bar in the Navigation Bar:

navigationController?.navigationBar.prefersLargeTitles = true // Navigation bar large titles
navigationItem.title = "Contacts"
navigationController?.navigationBar.largeTitleTextAttributes = [NSAttributedStringKey.foregroundColor : UIColor.white]
navigationController?.navigationBar.barTintColor = UIColor(displayP3Red: 0/255, green: 150/255, blue: 136/255, alpha: 1.0)

let searchController = UISearchController(searchResultsController: nil) // Search Controller
navigationItem.hidesSearchBarWhenScrolling = false
navigationItem.searchController = searchController

You can find an example for UISearchBarController - SearchBar and scope buttons overlap here.

Rheims answered 30/12, 2017 at 12:8 Comment(0)
P
0

I had the same issue in iOS 11.

Contrary to some of the comments here, if I look at your screenshots you DONT want to set it as the navigationItem because you don't have a UINavigationController setup.

Neither do you want to add the searchBar in the header of the tableView because for some reason it can't cope with the scopeBar

So what I did to fix it:

To get a UISearchBar with scopes over your tableView, use a UIViewController in interface builder not a UITableViewController.

Place a UISearchBar and a UITableView inside the view controller and wire them up properly (delegates, dataSource, etc).

Don't forget to change your swift file to UIViewController instead of UITableViewController as well and change it accordingly. (add a tableView property and connect it via IBOutlet, change the delegates for the tableView etc)

Then in interface builder, use autoLayout guides so the searchBar sits on top of the tableView

enter image description here

In interface builder when you activate the scope bar it will look totally weird but don't panic, it will be fine. I guess Apple screwed the rendering n interface builder when they changed the behavior to work with UINavigationController... anyway...

Then everything works as it should and look like this (in my case I present it the vc in a popover but that doesn't matter)

enter image description here

Packet answered 18/3, 2018 at 8:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.