I have set up a search bar using the embed nav bar. The func searchBarSearchButtonClicked is not being detected. I'd like to make it so that when the user taps on the search bar, another function will be called. I've taken out some extraneous code not relevant to this question. What could be the issue?
class FirstViewController: UIViewController, UISearchBarDelegate {
var resultSearchController: UISearchController? = nil
override func viewDidLoad() {
super.viewDidLoad()
// set up the search results table
let locationSearchTable = storyboard!.instantiateViewController(withIdentifier: "LocationSearchTable") as! LocationSearchTable
resultSearchController = UISearchController(searchResultsController: locationSearchTable)
resultSearchController?.searchResultsUpdater = locationSearchTable
let searchBar = resultSearchController!.searchBar
searchBar.sizeToFit()
searchBar.placeholder = "Where would you like to go"
navigationItem.titleView = resultSearchController?.searchBar
searchBar.delegate = self
resultSearchController?.hidesNavigationBarDuringPresentation = false
resultSearchController?.dimsBackgroundDuringPresentation = true
definesPresentationContext = true
}
func searchBarSearchButtonClicked(_: UISearchBar) {
// closeMapType()
// self.mapType.transform = .identity
print("it worked")
}
}
Below function will call when the user taps on the search bar :
func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool {
return true
}
This will call when we click on the "Search" button in the keyboard
func searchBarSearchButtonClicked(_: UISearchBar)
Related
I am trying to autofocus a searchbar when i click on a bar button, but it does not seem to work with becomeFirstResponder, follow the GIF:
I've already tried using becomeFirstResponder and it does not work, this is how i am handling the searchbar:
// MARK: SearchBar Delegate
#IBAction func showSearchBarAction(_ sender: Any) {
let searchController = UISearchController(searchResultsController: nil)
searchController.searchBar.delegate = self
searchController.searchResultsUpdater = self
searchController.searchBar.keyboardAppearance = .dark
searchController.dimsBackgroundDuringPresentation = false
navigationItem.searchController = searchController
navigationItem.searchController?.isActive = true
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
navigationItem.searchController?.isActive = false
self.navigationItem.searchController = nil
}
All of it works perfectly, but the autofocus is something i really want and i can't change my design as well
Solution
This code is the solution:
This is how my class declaration looks like:
class YourViewController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate, UISearchControllerDelegate {
// MARK: SearchBar Delegate
#IBAction func showSearchBarAction(_ sender: Any) {
let searchController = UISearchController(searchResultsController: nil)
searchController.delegate = self
searchController.searchBar.delegate = self
searchController.searchResultsUpdater = self
searchController.searchBar.keyboardAppearance = .dark
searchController.dimsBackgroundDuringPresentation = false
self.navigationItem.searchController = searchController
self.navigationItem.searchController?.isActive = true
}
func didPresentSearchController(_ searchController: UISearchController) {
DispatchQueue.main.async {
searchController.searchBar.becomeFirstResponder()
}
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
navigationItem.searchController?.isActive = false
self.navigationItem.searchController = nil
}
i want to disable right cancel button when a tap at search Bar.
Because of using Google Place search i put i should use searchController?.searchBar
I try to disable cancel button at
func presentSearchController(_ searchController: UISearchController) {
searchController.searchBar.showsCancelButton = false
}
but when i tap a searchBar i see how cancel button appear and disappear, thats looks ugly
Please give me advice!
override func viewDidLoad() {
super.viewDidLoad()
resultsViewController = GMSAutocompleteResultsViewController()
resultsViewController?.delegate = self
searchController = UISearchController(searchResultsController: resultsViewController)
searchController?.searchResultsUpdater = resultsViewController
searchController?.searchBar.sizeToFit()
navigationItem.titleView = searchController?.searchBar
searchController?.searchBar.placeholder = searchBarPlaceholderText
searchController?.searchBar.tintColor = #colorLiteral(red: 0.1019607843, green: 0.5490196078, blue: 1, alpha: 1)
searchController?.searchBar.delegate = self
searchController?.delegate = self
searchController?.searchBar.searchBarStyle = .prominent
definesPresentationContext = true
mapView.delegate = self
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
checklocationAuthorizationStatus()
locationManager.requestWhenInUseAuthorization()
locationManager.requestLocation()
locationManager.startUpdatingLocation()
}
func presentSearchController(_ searchController: UISearchController) {
searchController.searchBar.showsCancelButton = false
}
You can create a custom class and subclass UISearchBar and UISearchViewController.
For example:-
class CustomizedSearchBar: UISearchBar {
override func layoutSubviews() {
super.layoutSubviews()
setShowsCancelButton(false, animated: false)
}
}
Now Create Object of the CustomizedSearchBar and use it within other viewController.
Or you can create a customized searchViewController as follows:
class CustomizedSearchController: UISearchController, UISearchBarDelegate {
lazy var _searchBar: CustomSearchBar = {
[unowned self] in
let result = CustomSearchBar(frame: CGRectZero)
result.delegate = self
return result
}()
override var searchBar: UISearchBar {
get {
return _searchBar
}
}
}
Please follow this link for more detail information.
I have implemented searchBar using UISearchController using following code -
var searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.obscuresBackgroundDuringPresentation = false
searchController.searchBar.placeholder = "Search here..."
definesPresentationContext = true
searchController.searchBar.delegate = self
searchController.searchBar.sizeToFit()
if #available(iOS 11.0, *) {
self.navigationItem.searchController = searchController
} else {
// Fallback on earlier versions
navigationItem.titleView = searchController.searchBar
navigationItem.titleView?.layoutSubviews()
}
Now I have two issues-
SearchBar comes below the navigationBar(See the image attached), how do I get the searchBar on top of NavigationBar that used to come when we implement searchBar with UISearch bar.
The cancel button is not coming on the right side of search bar.
I don't think you can do this natively. But you can activate the search bar when you open the menu (dont forget to set searchController.hidesNavigationBarDuringPresentation to true):
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
searchController.isActive = true
}
But it will hide the UINavigationBar so this is not what you really want. So, maybe better, you can create a custom navigation bar and hide the native one. Here is a quick example:
1 - Create a swift a xib file NavigationBarView with an horizontal UIStackView, a back UIButton with a fixed width and a UISearchBar:
class NavigationBarView: UIView {
var backAction: (()->Void)?
#IBOutlet weak var searchBarView: UISearchBar!
override func awakeFromNib() {
super.awakeFromNib()
// Customize your search bar
self.searchBarView.showsCancelButton = true
}
#IBAction func backButtonPressed(_ sender: Any) {
self.backAction?()
}
}
2 - Instead of using a UITableViewController, create a UIViewController with a vertical UIStackView which contains a view with a fixed height of 64 and a UITableView:
class TableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var containerView: UIView!
let navigationBarView: NavigationBarView = NavigationBarView.viewFromNib() // Custom helper to instantiate a view, see below
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.isHidden = true // hide the native UINavigationBar
self.navigationBarView.backAction = {
self.navigationController?.popViewController(animated: true)
}
self.navigationBarView.searchBarView.delegate = self
self.navigationBarView.add(in: self.containerView) // Custom helper to put a view in a container view, see below
// Other stuff
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
}
Here is my helpers:
extension UIView {
static public func viewFromNib <GenericView: UIView> () -> GenericView {
let className = String(describing: self)
guard let instance = UINib(nibName: className, bundle: nil)
.instantiate(withOwner: nil, options: nil).first as? GenericView else {
// If this happens, it means the xcodeproj is broken
fatalError("Ho no its broken!")
}
return instance
}
func add(in superView: UIView) {
self.translatesAutoresizingMaskIntoConstraints = false
superView.addSubview(self)
self.topAnchor.constraint(equalTo: superView.topAnchor).isActive = true
self.bottomAnchor.constraint(equalTo: superView.bottomAnchor).isActive = true
self.leftAnchor.constraint(equalTo: superView.leftAnchor).isActive = true
self.rightAnchor.constraint(equalTo: superView.rightAnchor).isActive = true
}
}
Yo can try below code and please let me know if you are facing any issue.
if self.searchController != nil {
self.searchController.isActive = false
}
isSearching = true
self.searchController = UISearchController(searchResultsController: nil)
self.searchController.searchResultsUpdater = self
self.searchController.delegate = self
self.searchController.searchBar.delegate = self
self.searchController.hidesNavigationBarDuringPresentation = false
self.searchController.dimsBackgroundDuringPresentation = false
self.navigationItem.titleView = searchController.searchBar
self.definesPresentationContext = false
self.searchController.searchBar.returnKeyType = .done
There is a property for this
searchController.hidesNavigationBarDuringPresentation = true
There is a gap, so it might be a white text Canel button. ou can know it for sure in Debugger Navigator (Cmd+7) -> View UI Hierarcy. White button text might be caused by custom navigation bar style
I have set up a UISearchController as a header for my tableview with the following code:
let mySearchController = UISearchController(searchResultsController: nil)
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
let keywords = searchBar.text
let finalKeywords = keywords?.replacingOccurrences(of: " ", with: "+")
searchUrl = "https://api.spotify.com/v1/search?q=\(finalKeywords!)&type=track&limit=20"
print(searchUrl)
callAlamo(url: searchUrl)
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(postCell.self, forCellReuseIdentifier: cellId)
tableView.separatorColor = .red
mySearchController.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
mySearchController.delegate = self as? UISearchControllerDelegate
tableView.tableHeaderView = mySearchController.searchBar
}
I adde a breakpoint at the searchBarButtonClicked function and at the print(searchUrl) inside of the function, but it never went to the breakpoints. Why is the searchBarSearchButtonClicked function not executing when I click on the search bar?
You are setting the wrong delegate. A UISearchBarController as a delegate property, but the method you are implementing is a UISearchBarDelegate method, so you need to set your object as the delegate for the search bar contained within the `UISearchBarController:
mySearchController.searchBar.delegate = self
I have a searchbar in my tableview header. For that i am using uisearchcontroler. But it update tablview data when i am texting in searchbar, i need to update tablview when search button in keyboard is clicked, because i get data for search in api and everytime when i am texting in searchbar it requesting and it takes long time. How i can resolve this?
var resultSearchController = UISearchController()
var indicator:UIActivityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray)
var ref=UIRefreshControl()
override func viewDidLoad() {
super.viewDidLoad()
self.resultSearchController = ({
let controller = UISearchController(searchResultsController: nil)
controller.searchResultsUpdater = self
controller.dimsBackgroundDuringPresentation = false
controller.searchBar.sizeToFit()
self.tableView.tableHeaderView = controller.searchBar
return controller
})()
indicator.frame = CGRectMake(0.0, 0.0, 40.0, 40.0);
indicator.center = view.center
view.addSubview(indicator)
indicator.bringSubviewToFront(view)
indicator.startAnimating()
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
getRequests.getType1(tableView,spinner: indicator)
ref.addTarget(self, action: #selector(Catalog1TableViewController.refresh(_:)), forControlEvents: UIControlEvents.ValueChanged)
ref.attributedTitle = NSAttributedString(string: "Загрузка")
tableView.addSubview(ref)
}
func updateSearchResultsForSearchController(searchController: UISearchController)
{
indicator.startAnimating()
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
tableView.reloadData()
getRequests.getProduct(tableView, spinner: indicator,name: searchController.searchBar.text!)
for item in getRequests.product {
if item.productTitle.containsString(searchController.searchBar.text!){
filteredTableData.append(item)
}
}
tableView.reloadData()
}
Try to implement UISearchBar Delegate method :
func searchBarSearchButtonClicked(searchBar: UISearchBar)
You should implement something like this in your view controller.
var resultSearchController = UISearchController()
resultSearchController.searchBar.delegate = self
extension ViewController: UISearchBarDelegate {
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
print("search button click")
}
}