UISearchBar x button pressed
Asked Answered
E

16

47

How handle the event when press the 'x' button?

I try this method but not works.

-(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar{

}

enter image description here

Errant answered 19/3, 2015 at 1:15 Comment(3)
can you add the code for how you have allocated the search bar?Stonybroke
Check out this postXerophthalmia
I have tried using the code but dont works in ios 8Errant
L
45

I don't think there's an easy way to hook into the X button.

However, you can hook into its direct consequence: cleared text.

Try this:

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

The side effect is this also gets called when you manually clear your text.

Limitless answered 1/12, 2015 at 21:57 Comment(3)
A more accurate description is that using this method to detect a clear button press is a hack. I can't believe Apple hasn't fixed this after all these years.Vitalis
if it doesn't work, adding _ should do it. That is: (_ searchBar: UISearchBar, textDidChange searchText: String)Bladderwort
With this you can't differentiate between deleting text with keyboard and pressing the x buttonPetrolic
V
22

A rather hacky way to do it but this works.

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.

Vitalis answered 3/10, 2018 at 5:44 Comment(2)
hacking? Apple never realized people would want to tap that X?Dresden
the shouldChangeTextIn is not called when the X is pressedClone
M
20

Swift 5.2, Xcode 11.4

This one worked for me.

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

     clearButton.addTarget(self, action: #selector(self.yourFunction), for: .touchUpInside)
}
Mannie answered 10/2, 2020 at 9:19 Comment(5)
Where exactly should this code be used? I've been trying to clear the text field for days now!Brant
@GuilhermeCrozariol , u can put this code anywhere like viewDidLoad() etc.Mannie
This relies on keypath "_clearButton" if Apple decides to change this key in the future, this will stop working.Convention
Yeah... till then maybe then will directly expose the button property.Mannie
This has to be best answer! Thanks KedarChalcopyrite
G
13

As stated in Apple's documentation there is a delegate method textFieldShouldClear(_:) in UITextFieldDelegate.

The text field calls this method in response to the user pressing the built-in clear button.

So

  1. conform to UITextFieldDelegate
  2. set the delegate of your searchBar's text field
  3. implement textFieldShouldClear(_:) method
class MyClass: UITextFieldDelegate {
   weak var seachBar: UISearchBar!

   override func viewDidLoad() {
       if #available(iOS 13.0, *) {
          searchBar.searchTextField.delegate = self
       } else {
          searchBar.textField.delegate = self
       }
   }

   func textFieldShouldClear(_ textField: UITextField) -> Bool {
        // your code
        return true
    }
}
Gerkman answered 9/9, 2021 at 14:20 Comment(0)
G
9

Simplest solution in Swift 5.0

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    if searchText.isEmpty {
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
            searchBar.resignFirstResponder()
        }
    }
}
Gremial answered 19/6, 2019 at 9:17 Comment(1)
Read the docs in the header.... - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText; // called when text changes (including clear)Irrational
H
5

I had the same issue and it was solve like that: In search controller that inherits from UISearchController I added conformance to UITextFieldDelegate.

Then in init method the following line was addd:

searchBar.searchTextField.delegate = self

And implementing

func textFieldShouldClear(_ textField: UITextField) -> Bool

allows to achieve the information that clear button was pressed

Homopterous answered 26/8, 2021 at 16:37 Comment(0)
S
4

I had the same issue, tried to solve it with accessing searchBar's subview textField but it caused my app crash, and with a last effort i found this post.

Another issue was that,

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText

is being called twice when cancel button clicked, see also this.

And lastly what i did is;

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
    if (![searchText isEqualToString:self.searchText]) {
        self.searchText = searchText;
        return;
    }
    NSLog(@"Clear clicked");
}

This solved my issue.

Siana answered 18/5, 2015 at 12:55 Comment(0)
H
4
self.mySearchBar.searchTextField.delegate = self

    extension myViewController: UISearchTextFieldDelegate {

    func textFieldShouldClear(_ textField: UITextField) -> Bool {
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
            self.mySearchBar.searchTextField.resignFirstResponder()
        }
        return true
    }
}
Hussar answered 29/11, 2019 at 13:37 Comment(0)
B
3

I think the simplest solution to this question is:

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
     if searchText.isEmpty {
             DispatchQueue.main.async {
                 searchBar.resignFirstResponder()
             }
 }
Blackstock answered 27/7, 2020 at 11:22 Comment(0)
S
2

This works for me

-(UITextField*)getUITexfieldInUISearchBar:(UIView*)aSearchBar{
UITextField *searchBarTextField;
for (UIView *subView in [aSearchBar subviews]){
    if ([subView isKindOfClass:[UITextField class]])
    {
        searchBarTextField = (UITextField *)subView;
        [searchBarTextField setDelegate:self];
        break;

    }else if ([subView isKindOfClass:[UIView class]]){
        [self getUITexfieldInUISearchBar:subView];
    }
}
  return searchBarTextField;
}

And you can use the TextFields Delegate

- (BOOL)textFieldShouldClear:(UITextField *)textField {
   //Do something here...
}
Sport answered 25/4, 2018 at 16:5 Comment(0)
F
2
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
    if (searchText.length == 0) {
         //clear button (x) on the search bar is cliecked, so clear the table
        [self clearTable];
    }
}
Foretopsail answered 8/1, 2019 at 6:1 Comment(0)
B
0
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String){
    print("searchText: \(searchText)")
    if searchText.count > 0
    {
        // Show ur content
    }
    else
    {
        // Hide your content
    }
}
Broch answered 27/11, 2017 at 11:43 Comment(0)
O
0

... just works

if(searchText.length==0||searchText==nil){
    [self.searchBar resignFirstResponder];
    [NSTimer scheduledTimerWithTimeInterval:0.1
                                     target:self
                                   selector:@selector(hideKeyboard)
                                   userInfo:nil
                                    repeats:NO];
}

- (void)hideKeyboard{
   [self.searchBar resignFirstResponder];
}
Orourke answered 2/4, 2019 at 15:45 Comment(0)
H
0

Until apple releases a proper delegate method for clear button event handling this will work as of Xcode 12. Requires: >=iOS13

Get a reference to the searchBar clearButton if possible.

UIButton *searchBarTextFieldClearButton = [self.searchBar.searchTextField valueForKey:@"_clearButton"];
if (searchBarTextFieldClearButton) {
    [searchBarTextFieldClearButton addTarget:self action:@selector(searchTextFieldClearButtonTapHandler) forControlEvents:UIControlEventTouchUpInside];
}

Swift:

extension UISearchTextField {
   var clearButton: UIButton? {
      return value(forKey: "_clearButton") as? UIButton
   }
}
searchBar.searchTextField.clearButton.addTarget(self, #selector(handler), .touchUpInside) //bllah

Very important to keep in mind that your "action - searchTextFieldClearButtonTapHandler" gets called last. That is, after the delegate method - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText

Herthahertz answered 17/11, 2020 at 17:56 Comment(0)
P
-1

You can hook up to "Cancel button" clicked event by conforming to "UISearchBarDelegate" and then implement "searchBarCancelButtonClicked" method

Pratte answered 28/12, 2016 at 17:9 Comment(2)
Nope, the cancel button is a different button which appears when setting searchBar.showsCancelButton = true.Actinal
Cancel button is different and "x" button is different. Did you check before posting if the "searchBarCancelButtonClicked" method is triggered on click of "x" button?Glycol
S
-2
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {


    let inputString = searchText.trimmingCharacters(in: NSCharacterSet.whitespacesAndNewlines)

    if inputString.characters.count > 0
    {

    }
    else
    {
          //Write code here for Clear button action
    }
}
Sikhism answered 19/7, 2017 at 14:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.