16

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,824
  • 17
  • 99
  • 186
HurkNburkS
  • 5,492
  • 19
  • 100
  • 183

15 Answers15

37

You need to get the textField of the Search Bar:

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

hope this help! =)

Soto_iGhost
  • 671
  • 1
  • 9
  • 12
10

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
  • 565
  • 9
  • 20
8

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,970
  • 5
  • 44
  • 65
kishorer747
  • 810
  • 1
  • 10
  • 24
  • @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
8

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,184
  • 25
  • 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
7

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.

5

Swift 3, based on @Alexsander answer:

searchBar.setImage(UIImage(), for: .clear, state: .normal)
oskarsprima
  • 109
  • 1
  • 2
5

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

[UITextField appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]].clearButtonMode = UITextFieldViewModeNever;
thijsonline
  • 1,048
  • 11
  • 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
4

Swift 5

Just add a single line below

searchBar.searchTextField.clearButtonMode = .never
Anurag Bhakuni
  • 2,379
  • 26
  • 32
3

Swift 3 solution :

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

Usage :

searchBar.textField.clearButtonMode = .never
Maor
  • 3,340
  • 3
  • 29
  • 38
2

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
  • 233
  • 2
  • 5
  • 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
2

Try this:

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

}
1

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
  • 617
  • 6
  • 4
1

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
  • 455
  • 4
  • 15
1

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.

1

thijsonline's answer in swift:

(UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self])).clearButtonMode = .never
Hemang
  • 26,840
  • 19
  • 119
  • 186