8

I am using a UISearchBar to match text input against entries in a database and display the matched results to the user in a UITableView, as they type.

All is well, however, I cannot find a way to alter the return key type of the search bar's keyboard. By default it replaces the standard return key with a Search button. Because I am doing a live search as the user types, I do not need this button and having it there and inactive has raised some usability issues.

Attempted solutions

  1. I can set a keyboard with the setKeyboard:UIKeyboardType method, however this doesn't seem to override the default setting of replacing the return key (on the standard keyboard) with a Search key and it does not allow access to change this return key.

  2. I have thought about using a UITextField, giving me access to the returnKeyType property through the UITextInputTraits protocol. My problem with this however is that I am implementing the UISearchBarDelegate method searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText, which I would lose with the UITextField.

Is there a way that I can keep the functionality of the search bar's delegate methods, whilst having legitimate access to the keyboard's return key?

In fact, almost the exact screen I am implementing is found in Apple's Clock application
Screenshot:
enter image description here

So any help on a clean solution would be much appreciated. Note the return key on the bottom right instead of the default Search button'.

Himanshu
  • 31,810
  • 31
  • 111
  • 133
Andy Barnard
  • 696
  • 1
  • 5
  • 15

9 Answers9

20

Slightly different in iOS 7 compared to the answer of @sudip.

for (UIView *subview in self.searchBar.subviews)
{
    for (UIView *subSubview in subview.subviews)
    {
        if ([subSubview conformsToProtocol:@protocol(UITextInputTraits)])
        {
            UITextField *textField = (UITextField *)subSubview;
            [textField setKeyboardAppearance: UIKeyboardAppearanceAlert];
            textField.returnKeyType = UIReturnKeyDone;
            break;
        }
    }
}
Martin Stolz
  • 5,176
  • 3
  • 21
  • 19
  • was looking for this answer as the old ones don't work anymore in iOS 7, thanks! – Hugo Logmans Oct 10 '13 at 06:45
  • Thanks. In order to make the Done key actually dismiss the keyboard, I also had to set the view controller as the delegate of the text field (before setting the returnKeyType) and implement a textFieldShouldReturn delegate method that includes [textField resignFirstResponder]. – arlomedia Jun 17 '14 at 17:53
  • I also found that I had to change the textField's delegate back to the UISearchBar in searchBarTextDidEndEditing, using another set of loops like those shown above. Otherwise if I dismissed the keyboard and then tried to edit the search text again, it wouldn't take the focus and become editable the second time. – arlomedia Jun 17 '14 at 19:15
  • @arlomedia No need to deal with setting/unsetting UITextField delegate, you can still listen to searchBarSearchButtonClicked: of UISearchBarDelegate. One additional thing that I needed, though was textField.enablesReturnKeyAutomatically = NO; to have Done available on empty text. – Andris Zalitis Sep 11 '14 at 22:03
  • 1
    Is there any better way to do this now ? – GoodSp33d Nov 05 '14 at 12:13
20

I tried all of these solutions without luck until I realized that in IOS8, you can just set searchBar.returnKey = .Done or whatever UIReturnKeyType you like. Sigh.

kellanburket
  • 12,250
  • 3
  • 46
  • 73
10

Try this:

for(UIView *subView in searchBar.subviews) {
    if([subView conformsToProtocol:@protocol(UITextInputTraits)]) {
        [(UITextField *)subView setKeyboardAppearance: UIKeyboardAppearanceAlert];
    }
}

If you want to dismiss the return key (i.e., make it do nothing), set the "returnKeyType" property on the UITextField subview to "UIReturnKeyDone" along with "keyboardAppearence".

Neo
  • 1,554
  • 2
  • 15
  • 28
  • Many thanks @Neo, an effective solution. UIView class reference does seem to warn against this approach: _"For complex views declared in UIKit and other system frameworks, any subviews of the view are generally considered private and subject to change at any time. Therefore, you should not attempt to retrieve or modify subviews for these types of system-supplied views. If you do, your code may break during a future system update."_ Is this approach App store safe? Thanks – Andy Barnard Dec 21 '11 at 09:40
  • Andy.. I know at least a couple of other developers who did this without facing any problems.. Also, we are only testing for the presence of a certain class. So it is App store safe because we are not using any private Apis. – Neo Dec 21 '11 at 17:40
  • Thanks for solution! Can I please know where to put this code? Bcoz I tried in search bar begin edtiong and also in viewDidLaod, but didnt work for me. – iOSDev May 31 '12 at 01:53
  • I put the code in searchBarTextDidBeginEditing and it worked. – arlomedia Jun 17 '14 at 17:50
2

I had to add some lines to Neo's answer. Here is my code to add a "Done" button for UISearchbar :

for(UIView *subView in sb_manSearch.subviews) {
    if([subView conformsToProtocol:@protocol(UITextInputTraits)]) {

        UITextField *t = (UITextField *)subView;
        [t setKeyboardAppearance: UIKeyboardAppearanceAlert];

        t.returnKeyType = UIReturnKeyDone;
        t.delegate = self;
        break;
    }
}
sudip
  • 2,781
  • 1
  • 29
  • 41
1

To change Search into Done text. Use below code.

youtSearchBar.returnKeyType = .done
Manish Mahajan
  • 2,062
  • 1
  • 13
  • 19
0

UPDATE : From iOS 7 onwards, the accepted answer will not work, below version will the work on iOS 7 onwards.

 UIView *subViews =  [[_searchBar subviews] firstObject];
        for(UIView *subView in [subViews subviews]) {
            if([subView conformsToProtocol:@protocol(UITextInputTraits)]) {
                [(UITextField *)subView setEnablesReturnKeyAutomatically:NO];
            }
        }
Shrey
  • 1,959
  • 2
  • 21
  • 44
0
for (UIView *subView in view.subviews) {
    if ([subView isKindOfClass:[UITextField class]])
    {
        UITextField *txt = (UITextField *)subView;

        @try {

            [txt setReturnKeyType:UIReturnKeyDone];
            [txt setKeyboardAppearance:UIKeyboardAppearanceAlert];
        }
        @catch (NSException * e) {

            // ignore exception
        }
    }
}
cmsygog
  • 1
  • 2
0

you can do it by :

- (void)viewDidLoad 
{
     // Adding observer that will tell you keyboard is appeared.
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) 
                                                 name:UIKeyboardDidShowNotification object:nil];        

    [super viewDidLoad];
}

- (void)keyboardDidShow:(NSNotification *)note 
{
    keyboardTest = [self getKeyboard];

    [keyboardTest setReturnKeyEnabled: YES];
}

- (id) getKeyboard  // Method that returns appeared keyboard's reference 
{
    id keyboardView;

    // locate keyboard view
    UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
    UIView* keyboard;

    for(int i=0; i<[tempWindow.subviews count]; i++) 
    {
        keyboard = [tempWindow.subviews objectAtIndex:i];

        if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 3.2) 
        {           
            if([[keyboard description] hasPrefix:@"<UIPeripheralHost"] == YES)
            {
                keyboard = [[keyboard subviews] objectAtIndex:0];
                keyboardView = keyboard ;
            }
        } 
        else
        {
            if([[keyboard description] hasPrefix:@"<UIKeyboard"] == YES)
                keyboardView = keyboard ;
        }

    }
    return keyboardView ;
}
Maulik
  • 19,348
  • 14
  • 82
  • 137
-1

I just found the simplest wait to hack this, just put a blank when beginning editing search field

-(void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar{
    //Add a blank character to hack search button enable
    searchBar.text = @" ";}    
JasonD
  • 11
  • 3