UISearchBar in Navigation Bar cannot enter text - ios

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.

Related

How to set Search Bar's text on Navigation Bar Title Text?

I am getting idea of a new app. I love to find a many tricks. however, No luck for me.
The simple.
You can see swipe down the search bar from the below of the navigation bar.
Result:
// iOS 13 Navigation Bar only
self.navigationItem.title = "Search Title"
self.navigationController?.navigationBar.prefersLargeTitles = true
self.navigationController?.navigationItem.largeTitleDisplayMode = .never
UINavigationBar.appearance().isTranslucent = false
let app = UINavigationBarAppearance()
let navigationBar = self.navigationController?.navigationBar
app.backgroundColor = .clear
app.configureWithOpaqueBackground()
app.titleTextAttributes = [.foregroundColor: UIColor.label]
app.largeTitleTextAttributes = [.foregroundColor: UIColor.label]
app.backgroundColor = .systemGroupedBackground
self.navigationController?.navigationBar.scrollEdgeAppearance = app
navigationBar!.standardAppearance = app
navigationBar!.scrollEdgeAppearance = app
Search Result:
// Search Bars
let search = UISearchController(searchResultsController: nil)
search.searchBar.delegate = self
search.searchResultsUpdater = self as? UISearchResultsUpdating
search.searchBar.placeholder = "Search"
search.searchBar.searchTextField.tintColor = UIColor.gray
search.searchBar.setImage(UIImage(named: "magnifyingglass")?.withTintColor(UIColor.systemGray), for: .search, state: .normal)
self.navigationItem.searchController = search
(UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]) ).defaultTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.init(white: 100, alpha: 0.50)]
let textField = search.searchBar.value(forKey: "searchField") as! UITextField
let glassIconView = textField.leftView as! UIImageView
glassIconView.image = glassIconView.image?.withRenderingMode(.alwaysTemplate)
glassIconView.tintColor = UIColor.systemGray
let clearButton = textField.value(forKey: "clearButton") as! UIButton
clearButton.setImage(clearButton.imageView?.image?.withRenderingMode(.alwaysTemplate), for: .normal)
clearButton.tintColor = UIColor.systemGray
Now, I am tried to look for the trick code to set the search bar's text will appear navigation bar when you have searched it. (Yes, It is a very familiar to Safari style).
I don't like Search Bar title text stayed on the small of the search bars, so move to a large title look better.
Let me know. :)
You can use searchBarSearchButtonClicked method of UISearchBarDelegate.
(https://developer.apple.com/documentation/uikit/uisearchbardelegate/1624294-searchbarsearchbuttonclicked)
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
self.navigationItem.title = searchBar.text ?? "Search Title"
}
If you need to update the title as the user types in search bar, use updateSearchResults of UISearchResultsUpdating. (https://developer.apple.com/documentation/uikit/uisearchresultsupdating/1618658-updatesearchresults)
func updateSearchResults(for searchController: UISearchController) {
self.navigationItem.title = searchController.searchBar.text ?? "Search Title"
}

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.

How do I avoid the weird gap between search bar and the table view while search results displaying?

Check: Screenshot
I tried solutions to all relevant questions. However none of them helped really.
I am getting a weird gap between table view and search bar when search bar shows results.
Help me find out what's wrong with my code:
the view controller subclasses from UITableViewController, UISearchBarDelegate, UISearchResultsUpdating
var searchController = UISearchController()
var resultsController = UITableViewController()
var refreshController = UIRefreshControl()
in override :
configureSearchController()
resultsController.tableView.delegate = self
resultsController.tableView.dataSource = self
refreshController.attributedTitle = NSAttributedString(string: "")
refreshController.addTarget(self, action: #selector(refreshSelector), for: .valueChanged)
tableView.addSubview(refreshController)
searchController.searchBar.delegate = self
automaticallyAdjustsScrollViewInsets = false
definesPresentationContext = true
#objc func refreshSelector()
{
if(!searchLoaded)
{
searchLoaded = true
self.tableView.tableHeaderView = searchController.searchBar
self.navigationItem.rightBarButtonItem = nil
print( "Got ya")
}
refreshController.endRefreshing()
}
func configureSearchController ()
{
searchController = UISearchController(searchResultsController: resultsController)
searchController.searchResultsUpdater = self
searchController.searchBar.layer.borderWidth = 1;
searchController.searchBar.barTintColor = UIColor.searchBarBackgroundGrey()
searchController.searchBar.layer.borderColor = UIColor.searchBarBackgroundGrey().cgColor
self.navigationController?.navigationBar.shadowImage = UIImage()
}
deployment target has been set as 9.3

Start search after three letters in uisearchcontroller

I would like uisearchcontroller to start searching after I type at least three characters in search bar. So, what should I do for that ?
func configureSearchController() {
// Initialize and perform a minimum configuration to the search controller.
searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
searchController.searchBar.placeholder = "Search"
searchController.searchBar.delegate = self
searchController.searchBar.sizeToFit()
let textFieldInsideSearchBar = searchController.searchBar.valueForKey("searchField") as! UITextField
textFieldInsideSearchBar.font = UIFont(name: "Bauhaus", size: 19)
searchController.searchBar.setImage(UIImage(named: "searchikon"), forSearchBarIcon: UISearchBarIcon.Search, state: UIControlState.Normal);
// Place the search bar view to the tableview headerview.
TableView.tableHeaderView = searchController.searchBar
All you need to is add the single required method for the UISearchController.
func updateSearchResultsForSearchController(searchController: UISearchController) {
if searchController.searchBar.text?.characters.count > 2 {
// Filter your search results here
}
}
You will want to check the the length of the characters in an event which checks the change in the text field:
nameOfString.characters.count

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