How to search when search button clicked in keyboard? - ios

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")
}
}

Related

iOS - How to dismiss keyboard from the navigationItem.searchController when tap anywhere on the UIView?

I have implemented the new SearchController with its searchBar and the searchResultsController.
Here is how I implemented it :
The resultViewController:
lazy var resultViewController: SearchResultViewController = {
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let searchResultViewController = storyboard.instantiateViewController(withIdentifier: "SearchResultViewController") as! SearchResultViewController
searchResultViewController.delegate = self
return searchResultViewController
}()
And this is the SearchController:
lazy var searchController: UISearchController = {
let searchController = UISearchController(searchResultsController: resultViewController)
searchController.searchBar.delegate = self
searchController.obscuresBackgroundDuringPresentation = true
searchController.searchResultsUpdater = self
searchController.searchBar.placeholder = "Search.city.label".localizable()
searchController.searchBar.tintColor = UIColor.white
searchController.searchBar.barTintColor = UIColor.white
UITextField.appearance(whenContainedInInstancesOf: [type(of: searchController.searchBar)]).tintColor = UIColor(red:0.00, green:0.47, blue:0.78, alpha:1.0)
if let textfield = searchController.searchBar.value(forKey: "searchField") as? UITextField {
if let backgroundview = textfield.subviews.first {
// Background color
backgroundview.backgroundColor = UIColor.white
// Rounded corner
backgroundview.layer.cornerRadius = 10;
backgroundview.clipsToBounds = true;
}
}
definesPresentationContext = true
return searchController
}()
In my viewWillAppear I set the navigationItem.searchController :
self.searchController.isActive = true
if #available(iOS 11.0, *) {
self.navigationItem.searchController = searchController
self.navigationItem.hidesSearchBarWhenScrolling = true
} else {
// Fallback on earlier versions
}
I have been able to handle the cancelButtonClicked :
extension HomeViewController: UISearchBarDelegate {
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchBar.endEditing(true)
self.searchController.isActive = false
}
}
This is doing the "cancel" animation, hiding keyboard + inactive state on searchBar/searchController. Both at the same time, with 1 tap on cancel Button.
But I am unable to achieve this when the user tap anywhere on the view.
I tried with tap gesture but it requires me 2 tap to achieve the same behavior.
NB:
I got an UICollectionView in my UIViewController, which takes all the place in the UIView.
Here is what I have tried :
override func viewDidLoad() {
super.viewDidLoad()
handleTapAnywhereToRemoveKeyboard()
}
func handleTapAnywhereToRemoveKeyboard() {
let singleTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.singleTap(sender:)))
//singleTapGestureRecognizer.numberOfTapsRequired = 1
singleTapGestureRecognizer.cancelsTouchesInView = false
self.view.addGestureRecognizer(singleTapGestureRecognizer)
}
#objc func singleTap(sender: UITapGestureRecognizer) {
self.searchController.isActive = false
self.searchController.searchBar.resignFirstResponder()
self.searchController.searchBar.endEditing(true)
}
EDIT:
I was thinking, maybe it's because my searchBar and searchController aren't in the UIViewController's view hierarchy, but more in the NavigationController one.
So I also tried with :
navigationController?.view.endEditing(true)
I then was thinking, maybe it's because the UIScrollView within my UICollectionView is catching the tap.
So I tried to link the tap gesture on the UICollectionView instead of the UIView, but without success.
There is no need to add UITapGestureRecognizer as proposed above. UIViewContoller already conforms to UIResponder interface (legacy from Objective C), so you can override this method like this:
extension UIViewController {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.window?.endEditing(true)
super.touchesEnded(touches, with: event)
}
}
Please create UIViewController for dismiss keyboard througout application.
extension UIViewController {
func hideKeyboardWhenTappedAround() {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
#objc func dismissKeyboard() {
view.endEditing(true)
}
}
Use above code in your UIViewController file as below.
override func viewDidLoad() {
super.viewDidLoad()
self.hideKeyboardWhenTappedAround()
}
Update:
You can also use below code to dismiss keyboard from any class.
UIApplication.shared.sendAction(#selector(UIResponder.resign‌​FirstResponder), to: nil, from: nil, for: nil)
Try the solution from Dimple Desai but add the gesture recognizer to the TableView or CollectionView or whatever is laying on top of your UIView. Then it should work.
override func viewDidLoad(){
let tapView = UITapGestureRecognizer(target: self, action: #selector(self.hideKeyboard))
self.view.addGestureRecognizer(tapView)
}
#objc func hideKeyboard(tap: UITapGestureRecognizer){
self.view.endEditing(true)
}

How to disable cancel button of UISearchController.seachBar when i tap at searchBar?

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.

searchBarSearchButtonClicked is not being detected

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)

Hiding Cancel button on search bar in UISearchController

I'm trying to hide the Cancel button of the search bar in the UISearchController, but unfortunately setting the following in viewDidLoad() does not work:
override func viewDidLoad() {
super.viewDidLoad()
searchResultsTableController = UITableViewController()
searchResultsTableController.tableView.delegate = self
searchController = UISearchController(searchResultsController: searchResultsTableController)
searchController.searchResultsUpdater = self
searchController.searchBar.sizeToFit()
searchResultsView.tableHeaderView = searchController.searchBar
searchController.delegate = self
searchController.dimsBackgroundDuringPresentation = false
searchController.searchBar.delegate = self
searchController.searchBar.searchBarStyle = .Minimal
searchController.searchBar.showsCancelButton = false
definesPresentationContext = true
}
I have also tried using the above code in this delegate method:
func didPresentSearchController(searchController: UISearchController) {
searchController.searchBar.showsCancelButton = false
}
This approach works but will show the Cancel button briefly before hiding it, which is not ideal. Any suggestions?
I ended up subclassing both UISearchBar and UISearchController as suggested:
CustomSearchBar.swift
import UIKit
class CustomSearchBar: UISearchBar {
override func layoutSubviews() {
super.layoutSubviews()
setShowsCancelButton(false, animated: false)
}
}
CustomSearchController.swift
import UIKit
class CustomSearchController: 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
}
}
}
Rejoice! As of iOS 13, there is access to automaticallyShowsCancelButton on UISearchController. Set it to false to hide the cancel button.
func didPresentSearchController(_ searchController: UISearchController) {
searchController.searchBar.becomeFirstResponder()
searchController.searchBar.showsCancelButton = true
}
func didDismissSearchController(_ searchController: UISearchController) {
searchController.searchBar.showsCancelButton = false
}
In my case all the above solutions dint work. You need to show in didPresentSearchController and hide it in didDismissSearchController. Earlier I was just hiding in didDismissSearchController which was still showing Cancel button on cancelling.
Hide the Cancel button in search bar delegate methods and set your delegate searchController.searchBar.delegate=self UISearchBarDelegate
func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
}
func searchBarTextDidEndEditing(searchBar: UISearchBar) {
}
Try subclassing UISearchBar and implement:
override func layoutSubviews() {
super.layoutSubviews()
self.setShowsCancelButton(false, animated: false)
}
This SO thread may help you more in this direction.
The same answer as given by #Griffith and #Abhinav but using extension:
extension UISearchBar {
override open func layoutSubviews() {
super.layoutSubviews()
setShowsCancelButton(false, animated: false)
}
}
This code is from Swift 4.

Adding UISearchController to UIView

I'm trying to add a UIViewSearchController to ad UIView however it does not seem to show? So far I've created a subclass of UISearchController and UISearchBar. I've done that to remove the cancel button, from the searchController. However since i added these custom classes the searchBar does not show in the View? How come this that?
viewDidLoad in viewcontroller
//SearchController
backSearchView.backgroundColor = UIColor.clearColor()
self.resultSearchController = ({
let controller = MySearchController(searchResultsController: nil)
controller.hidesNavigationBarDuringPresentation = false
controller.dimsBackgroundDuringPresentation = false
controller.searchResultsUpdater = self
controller.dimsBackgroundDuringPresentation = false
controller.searchBar.sizeToFit()
controller.searchBar.frame = CGRectMake(8, 8, self.view.frame.width-16, 44)
controller.searchBar.setShowsCancelButton(false, animated: false)
controller.searchBar.backgroundImage = UIImage()
controller.searchBar.placeholder = "Søg"
controller.searchBar.returnKeyType = UIReturnKeyType.Default
controller.searchBar.delegate = self
let textFieldInsideSearchBar = controller.searchBar.valueForKey("searchField") as? UITextField
textFieldInsideSearchBar?.backgroundColor = UIColor.whiteColor()
textFieldInsideSearchBar?.clipsToBounds = true
textFieldInsideSearchBar?.layer.cornerRadius = 1
textFieldInsideSearchBar?.layer.borderWidth = 2
textFieldInsideSearchBar?.layer.borderColor = UIColor.whiteColor().CGColor
textFieldInsideSearchBar?.textColor = UIColor.darkGrayColor()
backSearchView.addSubview(controller.searchBar)
return controller
})()
SearchController subclass
class MySearchController: UISearchController, UISearchBarDelegate {
lazy var customSearchBar: NoCancelSearchBar = {
[unowned self] in
let result = NoCancelSearchBar(frame:CGRectZero)
result.delegate = self
return result
}()
override var searchBar: UISearchBar {
get {
return customSearchBar
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
SearchBar subclass
class NoCancelSearchBar: UISearchBar {
override func layoutSubviews() {
self.showsCancelButton = false
}
}

Resources