15

I would like to know how to hide or not display the UISearchBar cross that appears in the textField fo the UISearchBar

I have tried using this

filterSearchBar.showsCancelButton = NO;

However this is an actual cancel button not the small grey cross, so I would like to know if there is an equivalent for the small grey button that shows in the UISearchBar.

halfer
  • 19,471
  • 17
  • 87
  • 173
HurkNburkS
  • 5,452
  • 19
  • 95
  • 181

15 Answers15

36

You need to get the textField of the Search Bar:

UITextField *textField = [searchBar valueForKey:@"_searchField"];
textField.clearButtonMode = UITextFieldViewModeNever;

hope this help! =)

Soto_iGhost
  • 661
  • 1
  • 9
  • 12
9

There's a better way to do this, and you don't have to use private APIs or traverse subviews to do it, so this solution is App Store safe.

UISearchBar has a built-in API for doing this:

[UISearchBar setImage:forSearchBarIcon:state]

The SearchBar icon key you want is UISearchBarIconClear, and you want the UIControlStateNormal state. Then give it a clear image for the image, and you're done.

So, it should look like this:

[searchBar setImage:clearImage forSearchBarIcon:UISearchBarIconClear state:UIControlStateNormal];
Alexander
  • 555
  • 9
  • 19
7

Based on @Gines answer, here is the Swift version:

func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
    guard let firstSubview = searchBar.subviews.first else { return }

    firstSubview.subviews.forEach {
        ($0 as? UITextField)?.clearButtonMode = .never
    }
}
sunkehappy
  • 8,724
  • 5
  • 41
  • 63
kishorer747
  • 800
  • 1
  • 7
  • 23
  • @Tom thanks for the edit. Looks perfect. Is this a correct approach? – kishorer747 Aug 09 '16 at 10:00
  • 1
    I actually think Soto_iGhost's approach is best to solve this particular problem. But when I saw your code I couldn't help myself to edit it ☺️ There are of course many approaches to write this same piece of logic, but I like this one the best. – Tom van Zummeren Aug 10 '16 at 08:27
7

Swift 4

Adding to Alexander's answer and block user interaction on clear button:

To hide button:

searchBar.setImage(UIImage(), for: .clear, state: .normal)

To disable user interaction on the clear button, simply subclass UISearchBar

class CustomSearchBar: UISearchBar {

    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        let view = super.hitTest(point, with: event)
        if view is UIButton {
            return view?.superview // this will pass-through all touches that would've been sent to the button
        }
        return view
    }
}
Charlton Provatas
  • 2,068
  • 23
  • 18
  • This is a good solution for swift 4+, I have been using above methods which takes "_searchField" as key. but application is crashing at iOS 13.2.2. This solution has fixed my problem both for lower iOS versions and latest one. – Muhammad Adil Dec 01 '19 at 09:46
5

Swift 5

Tested on iOS 13

One liner working for me:

searchBar.searchTextField.clearButtonMode = .never

You can also set it to .whileEditing to have it displayed when the user is typing and then removed when the search bar loses focus.

4

You can remove the clear text button for all UISearchBar instances:

[UITextField appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]].clearButtonMode = UITextFieldViewModeNever;
thijsonline
  • 959
  • 8
  • 15
  • THIS is the only valid non-hackish answer. Good job! – Jan Jan 16 '18 at 22:07
  • This answer looks good - can we still set it for a search bar of a particular view-controller class? I've searchbar at multiple places and need to update this for only one class. – Hemang Aug 21 '19 at 09:05
3

Swift 3, based on @Alexsander answer:

searchBar.setImage(UIImage(), for: .clear, state: .normal)
3

Swift 5

Just add a single line below

searchBar.searchTextField.clearButtonMode = .never
Anurag Bhakuni
  • 2,281
  • 23
  • 32
2

Swift 3 solution :

extension UISearchBar{
    var textField : UITextField{
        return self.value(forKey: "_searchField") as! UITextField
    }
}

Usage :

searchBar.textField.clearButtonMode = .never
Maor
  • 3,040
  • 3
  • 27
  • 37
1

I tried different solutions about this issue, even the one selected in this post, but they didn't work.

This is the way I found to solve this issue:

UIView *subview = [[searchBar subviews] firstObject]; //SearchBar only have one subview (UIView)

//There are three sub subviews (UISearchBarBackground, UINavigationButton, UISearchBarTextField)
for (UIView *subsubview in subview.subviews)
{
    //The UISearchBarTextField class is a UITextField. We can't use UISearchBarTextField directly here.
    if ([subsubview isKindOfClass: [UITextField class]])
    {
            [(UITextField *)subsubview setClearButtonMode:UITextFieldViewModeNever];
    }
}
Ginés SM
  • 203
  • 2
  • 4
  • thanks, it worked!, the key was to search through subviews of first subview of Searchbar. See my answer for swift version – kishorer747 Jul 25 '16 at 09:47
1

Try this:

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
    UITextField *textField = [searchBar valueForKey:@"_searchField"];
    textField.clearButtonMode = UITextFieldViewModeNever;

}
0

In Case of Swift 2.3 just use :

var searchBar = UISearchBar();
searchBar.frame = CGRectMake(0, 0, 00, 20))
for subview: UIView in (searchBar.subviews.first?.subviews)!
        {
            if (subview.isKindOfClass(UITextField) )
            {
                let textFieldObject = (subview as! UITextField)
                textFieldObject.clearButtonMode = .Never;
            }
        }
Bijendra Singh
  • 559
  • 5
  • 4
0

Swift 2.3, based on @Alexsander answer:

searchBar.setImage(UIImage(named: "SearchClearIcon"), forSearchBarIcon: UISearchBarIcon.Clear, state: UIControlState.Highlighted)
searchBar.setImage(UIImage(named: "SearchClearIcon"), forSearchBarIcon: UISearchBarIcon.Clear, state: UIControlState.Normal)
Nemanja
  • 447
  • 4
  • 15
0

Converting Soto_iGhost's answer to Swift 4:

func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {

    let textField: UITextField = searchBar.value(forKey: "_searchField") as! UITextField
    textField.clearButtonMode = .never
}

If you have an outlet of UISearchBar the you can write above code anywhere in your class.

0

thijsonline's answer in swift:

(UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self])).clearButtonMode = .never
Hemang
  • 26,372
  • 18
  • 120
  • 180