Uisearchcontroller in Navigationitem iOS 11 Apple Way

iOS 11 UISearchBar in UINavigationBar

Now it's what you want...

if #available(iOS 11.0, *) {
let sc = UISearchController(searchResultsController: nil)
sc.delegate = self
let scb = sc.searchBar
scb.tintColor = UIColor.white
scb.barTintColor = UIColor.white

if let textfield = scb.value(forKey: "searchField") as? UITextField {
textfield.textColor = UIColor.blue
if let backgroundview = textfield.subviews.first {

// Background color
backgroundview.backgroundColor = UIColor.white

// Rounded corner
backgroundview.layer.cornerRadius = 10;
backgroundview.clipsToBounds = true;

}
}

if let navigationbar = self.navigationController?.navigationBar {
navigationbar.barTintColor = UIColor.blue
}
navigationItem.searchController = sc
navigationItem.hidesSearchBarWhenScrolling = false

}

Result:

Sample Image

Sample Image


With Rounded corner:

Animation with rounded corner is also working fine.

Sample Image

Broken UISearchBar animation embedded in NavigationItem

It looks like Apple still needs to iron out the use of the UISearchBar in the new large title style. If the UIViewController you push to doesn't have its navigationItem.searchController set, the animation works fine. When navigating between two instances of UIViewController that both have a searchController set, you get the issue you describe where the height of the navigation bar jumps.

You can solve (work around) the problem by creating the UISearchController every time viewDidAppear gets called (instead of creating it in loadView) and setting navigationItem.searchController to nil on viewDidDisappear.

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)

DispatchQueue.main.async {
let stvc = UITableViewController()
stvc.tableView.dataSource = self

let sc = UISearchController(searchResultsController: stvc)
sc.searchResultsUpdater = self
self.navigationItem.searchController = sc
}
}

override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)

self.navigationItem.searchController = nil
}

The reason for the asynchronous dispatch is that when setting the navigationItem.searchController inline in the viewDidAppear method, an exception is raised:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Only one palette with a top boundary edge can be active outside of a transition. Current active palette is <_UINavigationControllerManagedSearchPalette: 0x7fad67117e80; frame = (0 116; 414 0); layer = <CALayer: 0x60400002c8e0>>'

I know this is only a work around, but hopefully this will help you for now, until Apple solves the issue with navigating between two view controllers that both have a UISearchController set on their navigationItem.



Related Topics



Leave a reply



Submit