Dismiss UISearchBar keyboard without affecting cancel button - ios

I am trying to reproduce the functionality that can be seen in the contacts app on the iphone. I have a UISearchBar that dismisses the keyboard when the search button is clicked. This however deactivitates the cancel button and it requires 2 touches to activate. On the contacts app it is not deactivated when the search button is clicked and the keyboard is dismissed.
So what I am asking is how to dismiss the keyboard without deactivating the cancel button on the uiSearchBar?
I have tried
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
//Some other code
//I have Tried
//Attempt 1
self.searchBar.endEditing(true)
//Attempt 2
self.searchBar.resignFirstResponder()
//Attempt 3
var textFieldInsideSearchBar = searchBar.valueForKey("searchField") as? UITextField
textFieldInsideSearchBar.endEditing(true)
}

Delegate method parses you searchBar, so you do not have to use self.searchBar, that might be one of the issues. I usually use logic from your "Attempt 2".
You can try to implement this:
func searchBarTextDidEndEditing(_ searchBar: UISearchBar)
And call searchBar.resignFirstResponder().
If it does not work, then try to implement this method and return true:
func searchBarShouldEndEditing(_ searchBar: UISearchBar) -> Bool
If you are using UISearchBar in combination with UISearchDisplatController, then try this method on searchDisplayController:
func setActive(_ visible: Bool, animated animated;: Bool)

It quite bit tricky.
Try,
[self.searchBar resignFirstResponder];
[(UIButton *)[self.searchBar valueForKey:#"_cancelButton"] setEnabled:YES];

Related

Why searchBarTextDidEndEditing not called?

I have this code:
extension VC : UISearchBarDelegate
{
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
print("searchBarTextDidEndEditing")
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
// searchBar.resignFirstResponder()
}
}
searchBarCancelButtonClicked has fired when clicked on search , but searchBarTextDidEndEditing has not fire until I call searchBar.resignFirstResponder()
I read a lot of questions and answers about that, but I did not understand why is that happen, and what is resignFirstResponder() do here?
As stated in the documents resignFirstResponder
Notifies this object that it has been asked to relinquish its status as first responder in its window.
Basically this function call tells your input field that it should not be getting any more inputs from the user or the input action is finished for this input field. Thus your searchBarTextField ends it's editing status and searchBarTextDidEndEditing is called.
If you'd like to learn more about what a firstResponder is then you may want to checkout this part of the documentation.
This may be useful to some like myself wondering why similar delegate methods are not firing. Check you have set up all appropriate delegates for example:
searchController.searchResultsUpdater = self
searchController.searchBar.delegate = self

Swift 4 - How to enable / disable keyboard by using buttons

My tricky problem is :
I've 2 buttons with 2 UITextView.
Like you know, when I push an UITextView, keyboard appear. Well, this is not what I want.
I want to enable / disable the display's keyboard according a specific #IBAction taped.
The scenario is the following:
- First button (Keyboard icon) allow the user to display the keyboard to type something in one of the UITextView, with a FirstResponder init on the top one.
Second button (REC icon) allow the user to speak and display in pre-selected TextView but without displaying keyboard.
I already known that there is :
isUserInteractionEnabled
and
textViewDidBeginEditing
But it doesn't really fit well and/or fix my issue.
Here a screen to be more explicit (don't give a mind about the third green validate button, it's just for the .POST feature) :
Thanks for any help!
If I understand your problem correctly, You don't want the keyboard to appear when user taps on the textField but rather should come up only when user taps on Keyboard button and should dismiss on tapping other button.
All the posted answers mostly focus only on second part of showing keyboard and dismissing them on tapping button. Whats more tricky is preventing keyboard from appearing in when user taps on textField :)
Possible solutions you can try and their cons:
Solution 1:
Try setting textfield isEnabled = false sure this will prevent keyboard from appearing when user taps on textField but guess what Keyboard will not appear even on calling textfield.becomeFirstResponder() ahhh trouble :)
Solution 2:
implementing textFieldShouldBeginEditing of UITextField delegate and returing true or false based on whether used tapped on button or textField itself.
Sure it works but you will need to figure out way to tell textFieldShouldBeginEditing why was it triggered because of button or because of touch on textField again complications.
My Solution:
Use 2 textFields. One disable user interaction forever and use another textField which will never appear to user but will take care of showing keyboard when required.
Enough talk lets code :)
Step 1:
Lets say your textField which appears on screen is called textField
textfield.isEnabled = false
This will ensure whatever you do keyboard will not appear for this keyboard.
Step 2:
Create a temp textField of frame zero (which user can never tap :P )
tempTextField = UITextField(frame: CGRect.zero)
tempTextField.delegate = self
self.view.addSubview(tempTextField)
Step 3:
Now when user taps on show keyboard button, make your temp textField first responder
tempTextField.becomeFirstResponder()
and when user taps on other button resignFirstResponder for tempTextField.
tempTextField.resignFirstResponder()
Step 4:
But wait when user types nothing appears on my textField. Wait simply implement
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField == tempTextField {
self.textfield.text = (self.textfield.text ?? "") + string
}
return true
}
EDIT:
You don't really need two textFields, you can achieve the same with a UILabel and UITextField as well. I chose UITextField as I am not sure what are other requirements of yours!
Problem fixed. Hope it helps :)
Something like this should work:
class MyViewController: UIViewController, UITextViewDelegate {
#IBOutlet var yourTextView: UITextView
override func viewDidLoad() {
super.viewDidLoad()
yourTextView.delegate = self
}
#IBAction func showKeyboard(_ sender: UIButton) {
self.yourTextView.becomeFirstResponder()
}
#IBAction func hideKeyboard(_ sender: UIButton) {
self.yourTextView.resignFirstResponder()
}
}
You say
But it's not really working in my case.
Why?
You can disable the textfields interaction with (swift 3):
textField.isUserInteractionEnabled = false
Next, when you click on the keyboard button you can reenable the interaction so when the user click on one of the textfield the keyboard opens.
On the keyboard dismiss (you can see the UIKeyboardWillHideNotification callback notification) you can set the interaction to false.
function to dismiss KeyBoard when button is clicked:
#IBAction func hideKeyboard() {
textView.resignFirstResponder()
}
function to get keyboard to show up:
#IBAction func showKeyboard() {
textView.becomeFirstResponder()
}
Just copy and paste simple code for you accessory button embedded with keypad
func addKeyboardToolbar() {
let ViewForDoneButtonOnKeyboard = UIToolbar()
ViewForDoneButtonOnKeyboard.sizeToFit()
let button = UIButton.init(type: .custom)
button.setImage(UIImage.init(named: "login-logo"), for: UIControlState.normal)
button.addTarget(self, action:#selector(doneBtnfromKeyboardClicked), for:.touchUpInside)
button.frame = CGRect.init(x: 0, y: 0, width:UIScreen.main.bounds.width, height: 30) //CGRectMake(0, 0, 30, 30)
let barButton = UIBarButtonItem.init(customView: button)
ViewForDoneButtonOnKeyboard.items = [barButton]
postTextView.inputAccessoryView = ViewForDoneButtonOnKeyboard
}
#IBAction func doneBtnfromKeyboardClicked (sender: Any) {
self.contentView.endEditing(true)
}

UISearchBar searchBarCancelButtonClicked not being called using Swift 3

For some reason when I click the circle x cancel button in a UISearchBar the searchBarCancelButtonClicked event is not firing, it worked in a swift 2 project but not in this swift 3 one.
I am now extending my view controller instead of the inline class way but I believe that is working as the searchBarSearchButtonClicked event does work. Here is what I have so far:
extension MyViewController: UISearchBarDelegate {
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
print("here?")
searchBar.resignFirstResponder()
handleCancelSearch()
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
searchBar.resignFirstResponder()
if let searchText = searchBar.text {
performSearchUsing(term:searchText)
}
}
}
The print is not logged and the function not called. Am I missing something silly?
Maybe you are missing something silly as I did, the "circle x" is not actually the cancel button, and I thought that too, the cancel button comes disabled by default, you can activate it via storyboard on the attributes of the searchBar or you can do it programmatically with:
searchBar.showsCancelButton = true
After that, the method should work.
If any one still looking for the option how act on "X" button. use below method which is available in
UISearchBarDelegate
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String)
{
if searchText.count == 0
{ // Hide content
}
}
Note : it is not cannel button its clear text button which is visible after typing something in searchBar

How to resignfirstResponser on x button action event in uisearch bar?

I am unable to detect x button action in UISearchBar iOS 9. is there anyone can help me?
if your view controller is your search bar delegate, you could implement searchBarCancelButtonClicked function and resignFirstResponder from there.
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
searchBar.text = ""
searchBar.resignFirstResponder()
// or you could force view to end editing mode using self.view.endEditing(true)
}
you can do something like,
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
if searchText.characters.count == 0 {
performSelector("hideKeyboardWithSearchBar:", withObject:searchBar, afterDelay:0)
}
}
refer apple documentation for more details
Hope this will help :)
func hideKeyboardWithSearchBar(bar:UISearchBar) {
bar.resignFirstResponder()
}

UISearchBar triggered functions

My entire app interface is made programatically from ViewController.swift
Inside the view is UISearchBar. What are the names of functions which I can override in order to run my own code when UISearchBar is tapped on, when the keyboard's Search button is pressed and when UISearchBar's Cancel button is pressed?
If they don't exist, can I trigger my own functions at those times?
You'll want to add conformance to the UISearchBarDelegate protocol to your view controller:
extension ViewController : UISearchBarDelegate {
func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
// ...
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
// ...
}
}
and then set the search bar's delegate to self.
If you use the UISearchBarDelegate you can implement the following methods...
//Becomes first responder
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar;
//Editing begins
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar;
//Cancel button pressed
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar;

Resources