UISearchController does not cover status bar with opaque UINavigationBar - ios

I have researched this problem a lot but I have found no solution that would work for me.
Basically, I have a UIViewController that presents UISearchController like this:
let searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.delegate = self
searchController.dimsBackgroundDuringPresentation = false
searchController.searchBar.delegate = self
view.addSubview(searchController.searchBar)
User is then expected to tap the UISearchBar to present searchController and reveal the keyboard. However, a strange thing happens during the transition between controllers.
It seems as if the UISearchController didn't cover the status bar and let you see the UIViewController that presented it below. I would like to find a way to prevent this, i.e. to force the search controller to extend all the way under the status bar.
Things that I have already done:
I have set self.definesPresentationContext = true in viewDidLoad:.
I have found out that this is a known bug, namely rdar://20942583.
I have attempted to circumvent the bug by setting:
self.edgesForExtendedLayout = .All
self.extendedLayoutIncludesOpaqueBars = true
It didn't work.
I'm running out of ideas. Please help.
Thanks a bunch,
Pete.

Facing the same issue and tried everything from here and here and none of this worked for me :(
Best workaround that is working (ugly I know) until I find a better solution:
override func viewDidLoad() {
super.viewDidLoad()
searchController.delegate = self
}
func willPresentSearchController(searchController: UISearchController) {
let statusHeight = UIApplication.sharedApplication().statusBarFrame.size.height
if bgBar == nil {
bgBar = UIView(frame: CGRectMake(0, 0, view.frame.width, (navigationController?.navigationBar.frame.height)! + statusHeight))
bgBar.backgroundColor = UIColor.redColor()
view.addSubview(bgBar)
} else {
bgBar.hidden = false
}
tableView.contentInset.top = statusHeight
}
func willDismissSearchController(searchController: UISearchController) {
bgBar.hidden = true
tableView.contentInset.top = 0
}

On swift 4:
viewWillAppear(_ animated: Bool) {
let statusHeight = UIApplication.shared.statusBarFrame.size.height
let sbview = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: statusHeight))
sbview.backgroundColor = .white
view.addSubview(sbview)
{

Related

How to make searchbar corner round

I am trying to make searchBar corner rounded. I have tried many ways of using layer.cornerRadius, maskToBound = true. I am loading the searchBar in the navigationBar programmatically. I have tried many solution given on stack-overflow but nothing worked.
func setupsearchbar()
{
// Setup the Search Controller
searchcontroller.searchResultsUpdater = self as? UISearchResultsUpdating
searchcontroller.hidesNavigationBarDuringPresentation = false
searchcontroller.searchBar.placeholder = "Search"
self.navigationItem.titleView = searchcontroller.searchBar
self.searchcontroller.searchBar.layer.cornerRadius = 30
self.searchcontroller.searchBar.layer.masksToBounds = true
definesPresentationContext = true
searchcontroller.searchBar.delegate = self
}
Please help if there is anything I can do.
Use following code which are working fine for me in my current project.
if let textfield = searchController.searchBar.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;
}
}
I hope this will help you.

centering search controller vertically iOS

I added UISearchController programmatically with code
let searchController = UISearchController(searchResultsController: nil)
override func viewDidLoad() {
super.viewDidLoad()
searchController.searchResultsUpdater = self
searchController.obscuresBackgroundDuringPresentation = false
searchController.searchBar.placeholder = "Введіть значення для пошуку"
searchController.searchBar.backgroundColor = .white
navigationItem.searchController = searchController
definesPresentationContext = true
}
But it seems that it is not centered vertically. How can I fix it?
Connected SearchController to TableView instead of NavigationItem
tableView.tableHeaderView = searchController.searchBar
It seems like a bug in iOS. For some reason at least on iOS 15 searchbar textfield frame has initial value of y = 1 but after you click on the field and then leave this field it will go to y = 8. Fixing the initial frame manually in viewDidLayoutSubviews solved this problem in my case:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
searchController.searchBar.searchTextField.frame.origin.y = 8
}

UISearchBar in Navigation Bar cannot enter text

I'm having a weird problem, when my app first loads you cannot enter text in the search bar no matter how many times you tap it, the search bar is nested in the navigation bar.
My app also use a tab bar, and when you switch tabs then go back to the tab with the search bar it allows you enter text... any ideas what's causing this?
Heres the code for the searchBar:
func setupSearchBar(){
let locationSearchTable = storyboard!.instantiateViewController(withIdentifier: "LocationSearchTable") as! LocationSearchTableViewController
resultSearchController = UISearchController(searchResultsController: locationSearchTable)
resultSearchController?.searchResultsUpdater = locationSearchTable
searchBar = resultSearchController!.searchBar
searchBar.sizeToFit()
searchBar.placeholder = "Location"
searchBar.isTranslucent = true
searchBar.isUserInteractionEnabled = true
for subView in searchBar.subviews{
for subsubView in subView.subviews{
if let textField = subsubView as? UITextField{
var currentTextFieldBounds = textField.bounds
currentTextFieldBounds.size.height = 40.0
textField.bounds = currentTextFieldBounds
textField.borderStyle = UITextBorderStyle.none
textField.textAlignment = NSTextAlignment.left
textField.font = UIFont(name: "System", size: 25.0)
textField.textColor = theme?.textColour
}
}
}
self.navigationController?.navigationBar.setBarColour(colour: (theme?.tabBarColour)!, tint: (theme?.textColour)!)
navigationItem.titleView = resultSearchController?.searchBar
navigationItem.titleView?.bringSubview(toFront: (resultSearchController?.searchBar)!)
searchBar.delegate = self
searchBar.showsSearchResultsButton = true
searchBar.setImage(#imageLiteral(resourceName: "location_icon.png"), for: UISearchBarIcon.resultsList, state: UIControlState.normal)
resultSearchController?.hidesNavigationBarDuringPresentation = false
resultSearchController?.dimsBackgroundDuringPresentation = true
definesPresentationContext = true
locationSearchTable.mapView = mapView
locationSearchTable.handleMapSearchDelegate = self
}
Ok after a lot messing around, I discovered that in my custom UITabBarController I had used override func viewWillAppear(_ animated: Bool) without adding super.viewWillAppear() and that caused the problem! I assume because of that subviews weren't being laid out correctly. Hope that helps anyone who has a similar problem to mine.

UISearchController not showing

I am working on Swift 3.1, I want a simple search functionality where the search results will show in a popOver manner below the search bar. This is a native offering and should be available using UISearchController. But even after my repeated trials, I could not achieve this. Am I missing something?
I have mentioned the resultsController. Implemented the required delegates and even the data us fed to it. But still its not shown.
Any help will be greatly appreciated. Thanks.
Code:
func initiateView() {
resultsController = ResultsController()
resultsController.table.dataSource = self
searchController = UISearchController.init(searchResultsController: resultsController)
self.view.addSubview(searchController.searchBar)
searchController.searchResultsUpdater = self
searchController.delegate = self
searchController.dimsBackgroundDuringPresentation = false // default is YES
searchController.searchBar.delegate = self // so we can monitor text changes + others
definesPresentationContext = true
feedTable = UITableView()
feedTable.delegate = self
feedTable.dataSource = self
feedTable.separatorStyle = .singleLineEtched
feedTable.register(UITableViewCell.self, forCellReuseIdentifier: "SomeCell")
self.view.addSubview(feedTable)
feedTable.pinToSuperview([.Left, .Right, .Bottom])
feedTable.pinToSuperviewTop(withInset: 50, priority: 100)
}
func updateSearchResults(for searchController: UISearchController)
{
if let searchString = searchController.searchBar.text{
let resultsController = searchController.searchResultsController as! ResultsController
resultsController.resultsArray = feedArray.filter({$0 .contains(searchString)})
resultsController.table.reloadData()
}
}

Get search bar in navigation bar in Swift

So I've tried everything trying to get a search bar into the navigation bar in Swift. But sadly I haven't gotten it working, just yet...
For those of you who don't know what I'm talking about, I'm trying to do something like this
Note the search bar in the navigation bar. So here's what I'm currently using
self.searchDisplayController?.displaysSearchBarInNavigationBar = true
I popped that in my viewDidLoad, and then when I load up the app I'm presented with, just an empty navigation bar.... :( Any ideas?
Try this
let leftNavBarButton = UIBarButtonItem(customView:Yoursearchbar)
self.navigationItem.leftBarButtonItem = leftNavBarButton
Update
You keep a lazy UISearchBar property
lazy var searchBar:UISearchBar = UISearchBar(frame: CGRectMake(0, 0, 200, 20))
In viewDidLoad
searchBar.placeholder = "Your placeholder"
var leftNavBarButton = UIBarButtonItem(customView:searchBar)
self.navigationItem.leftBarButtonItem = leftNavBarButton
If you want to use storyboard
just drag your searchbar as a outlet,then replace the lazy property with your outlet searchbar
// create the search bar programatically since you won't be
// able to drag one onto the navigation bar
searchBar = UISearchBar()
searchBar.sizeToFit()
// the UIViewController comes with a navigationItem property
// this will automatically be initialized for you if when the
// view controller is added to a navigation controller's stack
// you just need to set the titleView to be the search bar
navigationItem.titleView = searchBar
Swift 5, XCode 11, Storyboard way so you can easily add all the search bar attributes through the storyboard and you have less code in your view controller class.
1.) Add your search bar view as external view in viewcontroller.
2.) Connect searchBarView to you viewcontroller.
3.) Add your searchBarView to your navigationBar title item.
navigationItem.titleView = searchBarView
Result:
In your view controller:
lazy var searchBar = UISearchBar(frame: CGRectZero)
override func viewDidLoad() {
super.viewDidLoad()
searchBar.placeholder = "Search"
navigationItem.titleView = searchBar
}
Doing it this way, by setting the navigationItem.titleView, the search bar is automatically centered across the iPhone and iPad devices. Note: only tested with v8.4 and v9.0
for SWIFT 3
lazy var searchBar = UISearchBar(frame: CGRect.zero)
In 2019, you should use UISearchController.
override func viewDidLoad() {
super.viewDidLoad()
let searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self.viewModel
searchController.obscuresBackgroundDuringPresentation = false
searchController.searchBar.placeholder = "Search artists"
self.navigationItem.searchController = searchController
self.definesPresentationContext = true
}
And some class should conform to UISearchResultsUpdating. I usually add this as extension to my ViewModel.
extension ArtistSearchViewModel: UISearchResultsUpdating {
func updateSearchResults(for searchController: UISearchController) {
print("Searching with: " + (searchController.searchBar.text ?? ""))
let searchText = (searchController.searchBar.text ?? "")
self.currentSearchText = searchText
search()
}
}
This will spawn something like this:
For iOS 11 and above
navigationItem.searchController = searchController
For iOS 10 and below
navigationItem.titleView = searchController.searchBar;
or you can assign it as leftBarButtonItem as described in this answer
For Swift 5 or letter
also, you can use this code. Fully Programmatically
import UIKit
class SearchTableViewController: UITableViewController {
private lazy var searchController: UISearchController = {
let sc = UISearchController(searchResultsController: nil)
sc.searchResultsUpdater = self
sc.delegate = self
sc.obscuresBackgroundDuringPresentation = false
sc.searchBar.placeholder = "Enter A Compiny Name Or Symbole"
sc.searchBar.autocapitalizationType = .allCharacters
return sc
}()
override func viewDidLoad() {
super.viewDidLoad()
setupNavigationBar()
}
private func setupNavigationBar() {
navigationItem.searchController = searchController
}
}
// MARK: - UISearchResult Updating and UISearchControllerDelegate Extension
extension SearchTableViewController: UISearchResultsUpdating, UISearchControllerDelegate {
func updateSearchResults(for searchController: UISearchController) {
}
}
let searchBar = UISearchBar()
searchBar.sizeToFit()
searchBar.placeholder = ""
self.navigationController?.navigationBar.topItem?.titleView = searchBar
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
searchBar.endEditing(true)
searchBar.text = nil
print("## search btn clicked : \(searchBar.text ?? "")")
}
Setting SearchBar as titleView, changes height of navigationBar to 56. To fix this, you can embed searchBar in view and set that as titleView.
var offset: CGFloat = 20
// If VC is pushed, back button should be visible
if navigationController?.navigationBar.backItem != nil {
offset = 40
}
let customFrame = CGRect(x: 0, y: 0, width: view.frame.size.width - offset, height: 44.0)
let searchBarContainer = UIView(frame: customFrame)
searchBar = UISearchBar(frame: customFrame)
searchBarContainer.addSubview(searchBar)
navigationItem.titleView = searchBarContainer

Resources