Ahmed Saeed
Ahmed Saeed

Reputation: 13

UISearchBar cancel button not hiding the keyboard

I have tried each and everything and still, I could not hide the keyboard when I click on "cross" button in the search bar.

class SearchViewController: UIViewController, UISearchBarDelegate {

@IBOutlet weak var searchProfile: UISearchBar!
@IBOutlet weak var searchTableView: UITableView!
var searchArr: [String] = ["Shaheed Claim", "Shuhda Family Issues", "Show Cause Notices", "Punishments", "Appeal", "Suspension", "Enquiries", "Demotion", "Judicial Proceeding", "Criminal Record", "HRMIS Profile", "Transfer Posting", "Education", "Skill Assessment", "Sports Skill", "Family Profile", "Beneficiary Details", "Medical History", "Psycho Profile", "Asset Details","Official Items","My Leaves", "Attendance", "Absent Details", "Promotion", "Seniority", "Rewards", "ACR Details", "Dowry Charges", "Funeral Charges", "Last Month Salary", "Medical Charges", "Scholarships", "Maintenance Allowance", "Apply Leave", "Issuance of Documents", "Request Transfer Posting", "Establishment Matters", "Other Documents", "Pay & Allowances"]

var filteredData: [String] = []
override func viewDidLoad() {
    super.viewDidLoad()
    searchTableView.delegate = self
    searchTableView.dataSource = self
    searchProfile.delegate = self
    
    filteredData = searchArr
    
}

}

extension SearchViewController: UITableViewDelegate, UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return filteredData.count }

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = searchTableView.dequeueReusableCell(withIdentifier: "searchCell", for: indexPath)
    cell.textLabel?.text = filteredData[indexPath.row]
    return cell
}

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
     print("textdidchange")
     if searchText != "" {
         
          filteredData = searchArr.filter({$0.lowercased().contains(searchText.lowercased())})
         searchTableView.reloadData()
     } else {
          filteredData.removeAll()

         searchTableView.reloadData()
          
     }
}

func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
   // searchBar.text = ""
    print("searchcancel clicked")
    searchBar.endEditing(true)
}

}

I have tried, searchBar.resignFirstResponder() as well but not helping me.

One thing more to add, that this function is not calling I guess, because "searchcancel clicked" print is not printing on console. I have used debugger as well.

let me know how to make it work or is there anything I'm missing?

Here is the controller:

enter image description here

Upvotes: 0

Views: 92

Answers (1)

daredevil1234
daredevil1234

Reputation: 1445

The cancel button is a different button than what you are describing.

To see the cancel button on your UISearchBar searchProfile.showsCancelButton = true

UISearchBar cancel button, shown on right of text input. X button lives in text input field

You can see clearly that the X button you are looking for, and the cancel button are two different things. This cancel button calls searchBarCancelButtonClicked

to detect when that X is clicked, you will need something like:

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    if searchText == "" {
        print("UISearchBar.text cleared!")
    }
}

which in a way, you are already calling. If you add a print statement to your else inside textDidChange you should see it print on clicking the x

Next, you need to differentiate between a user clicking that x, and simply deleting the text in the search bar. Here is a quickly thrown together sample below:

private var didTapDeleteKey = false

func searchBar(_ searchBar: UISearchBar,
               shouldChangeTextIn range: NSRange,
               replacementText text: String) -> Bool
{
    didTapDeleteKey = text.isEmpty

    return true
}

func searchBar(_ searchBar: UISearchBar,
               textDidChange searchText: String)
{
    if !didTapDeleteKey && searchText.isEmpty {
        // Do something here
    }

    didTapDeleteKey = false
}

The success of this code hinges on the fact that when tapping the clear button of the search bar, searchBar(_:shouldChangeTextIn:replacementText:) -> Bool is not called. Instead when the delete button of the keyboard is tapped, the method is called.

alternatively, you can also try something like:

if let searchTextField = searchProfile.value(forKey: "searchField") as? UITextField , let clearButton = searchTextField.value(forKey: "_clearButton")as? UIButton {

     clearButton.addTarget(self, action: #selector(self.yourFunction), for: .touchUpInside)
}

This relies on keypath _clearButton if Apple decides to change this key in the future, this will stop working. You can call it in viewDidLoad or something else

Upvotes: 2

Related Questions