Remove clear button (grey x) to the right of UISearchBar when cancel button tapped

The problem is that UISearchBar doesn't expose it's text field, and manages the properties on the text field itself. Sometimes, the values of the properties aren't what you want.

For instance, in my own app, I wanted the keyboard style for my search bar to use the transparent alert style.

My solution was to walk through the subviews of the search bar until you find the text field. You should then be able to set the clearButtonMode property, using something like UITextFieldViewModeWhileEditing as a parameter.

This should make it so that the clear button is only shown while the text field is editing.

You want to do this on viewDidLoad or something early, so it's set before you start using it (but after the search bar is initialised.

for (UIView *subview in searchBar.subviews)
{
    if ([subview conformsToProtocol:@protocol(UITextInputTraits)])
    {
        [(UITextField *)subview setClearButtonMode:UITextFieldViewModeWhileEditing];
    }
}

Looks like iOS 7 changed the view hierarchy of UISearchBar, and the text box is deeper in the view (The above solution didn't work for me). However, modifying the above solution to traverse the whole hierarchy works:

[self configureSearchBarView:[self searchBar]];

- (void)configureSearchBarView:(UIView*)view {
    for (UIView *subview in [view subviews]){
        [self configureSearchBarView:subview];
    }
    if ([view conformsToProtocol:@protocol(UITextInputTraits)]) {
        [(UITextField *)view setClearButtonMode:UITextFieldViewModeWhileEditing];
    }
}

I'm building upon the previous answers because I started seeing crashes on iOS 7.1 unless I made the following change. I added an additional call to respondsToSelector for each view to make sure that setClearButtonMode: can be called. I observed an instance of UISearchBar getting passed in, which seems to conform to the UITextInputTraits protocol yet does not have the setClearButtonMode: selector, so a crash occurred. An instance of UISearchBarTextField also gets passed in and is the actual object for which to call setClearButtonMode:.

- (void)removeClearButtonFromView:(UIView *)view
{
    if (!view)
    {
        return;
    }

    for (UIView *subview in view.subviews)
    {
        [self removeClearButtonFromView:subview];
    }

    if ([view conformsToProtocol:@protocol(UITextInputTraits)])
    {
        UITextField *textView = (UITextField *)view;
        if ([textView respondsToSelector:@selector(setClearButtonMode:)])
        {
            [textView setClearButtonMode:UITextFieldViewModeNever];
        }
    }
}