iOS Change the title of cancel button in UISearchBar

I wish to change the title of the cancel button in iOS. I have been using this previously:

- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller{
  self.searchDisplayController.searchBar.showsCancelButton = YES;
  UIButton *cancelButton = nil;
  for (UIView *subView in self.searchDisplayController.searchBar.subviews) {
     if ([subView isKindOfClass:NSClassFromString(@"UIButton")]) {
         cancelButton = (UIButton*)subView;
     }
  }
  [cancelButton setTitle:@"Annuller" forState:UIControlStateNormal];
}

But it doesnt seem to work in iOS7. Any Suggestions?

  • Make an iPhone specific app work on iPad to meet Apple requirements
  • Swift UIViewReportBrokenSuperviewChain cause by Layer manipulation
  • Invalid result returned from the software lookup service
  • FMDatabaseQueue How To Return A Value
  • Swift optional binding with tuples
  • iOS 5 GM: <Error>: More than maximum 5 filtered album lists trying to register. This will fail
  • 13 Solutions Collect From Internet About “iOS Change the title of cancel button in UISearchBar”

    simply do this code for it:-

    - (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
    {
        /* when user start editing in serchbar this method will display cancel button and disable the autocorrection functionality */
    
        srcbar.showsCancelButton = YES;
    
        for (UIView *subView in searchBar.subviews) {
            if ([subView isKindOfClass:[UIButton class]]) {
               UIButton *cancelButton = (UIButton*)subView;
    
                [cancelButton setTitle:@"hi" forState:UIControlStateNormal];
            }
        }
        srcbar.autocorrectionType = UITextAutocorrectionTypeNo;
    
    }
    

    Not test in iOS7 but this working fine in iOS6 hope this working for you.

    OUTPUT IS:-

    enter image description here

    You need to search for the button recursively. This should be a fail-safe way to do it:

    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        [self convertButtonTitle:@"Cancel" toTitle:@"Annuller" inView:self.searchBar];
    }
    
    - (void)convertButtonTitle:(NSString *)from toTitle:(NSString *)to inView:(UIView *)view
    {
        if ([view isKindOfClass:[UIButton class]])
        {
            UIButton *button = (UIButton *)view;
            if ([[button titleForState:UIControlStateNormal] isEqualToString:from])
            {
                [button setTitle:to forState:UIControlStateNormal];
            }
        }
    
        for (UIView *subview in view.subviews)
        {
            [self convertButtonTitle:from toTitle:to inView:subview];
        }
    }
    

    I’ve tested this on iOS 7 only, but it works and should do so for iOS 6 too.

    here is my solution for both ios6 & ios7

    #define IS_IOS7 (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1)
    - (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller
    {
        self.searchDisplayController.searchBar.showsCancelButton = YES;
    
        UISearchBar *searchBar = self.searchDisplayController.searchBar;
        UIView *viewTop = IS_IOS7 ? searchBar.subviews[0] : searchBar;
        NSString *classString = IS_IOS7 ? @"UINavigationButton" : @"UIButton";
    
        for (UIView *subView in viewTop.subviews) {
            if ([subView isKindOfClass:NSClassFromString(classString)]) {
                UIButton *cancelButton = (UIButton*)subView;
                [cancelButton setTitle:@"your title" forState:UIControlStateNormal];
            }
        }
    }
    

    in order to make it work on iOS7, you have to search in the subview of search bar:

    //iOS 7 hack
    searchBar.showsCancelButton = YES;
    UIView* view=searchBar.subviews[0];
    for (UIView *subView in view.subviews) {
        if ([subView isKindOfClass:[UIButton class]]) {
            UIButton *cancelButton = (UIButton*)subView;
    
            [cancelButton setTitle:@"Anuluj" forState:UIControlStateNormal];
        }
    }
    

    Put this line in appDelegate

    [[UIButton appearanceWhenContainedIn:[UISearchBar class], nil] setTitle:@”Your Title” forState:UIControlStateNormal];

    For Swift 3.0

    This is working fine.

    func setSearchButtonText(text:String,searchBar:UISearchBar) {
    
        for subview in searchBar.subviews {
            for innerSubViews in subview.subviews {
                if let cancelButton = innerSubViews as? UIButton {
                    cancelButton.setTitleColor(UIColor.white, for: .normal)
                    cancelButton.setTitle(text, for: .normal)
                }
            }
        }
    
    }
    

    And call the method

    setSearchButtonText(text: "Done", searchBar: yourSearchBar)
    

    Here is the output

    enter image description here

    @Nitin Gohel Like so?

    - (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller{
      self.searchDisplayController.searchBar.showsCancelButton = YES;
      UIButton *cancelButton = nil;
      for (UIView *subView in self.searchDisplayController.searchBar.subviews) {
         if ([subView isKindOfClass:NSClassFromString(@"UIButton")]) {
             cancelButton = (UIButton*)subView;
    
             [cancelButton setTitle:@"Annuller" forState:UIControlStateNormal];
         }
     }
    
    }
    

    It seems like “self.searchDisplayController.searchBar.subviews” just return the “searchBar” itself. I tried bellow, and it works!

    for (UIView *searBarView in [self.searchDisplayController.searchBar subviews])
    {
        for (UIView *subView in [searBarView subviews]) 
        {
            if ([subView isKindOfClass:[UIButton class]])
            {
                UIButton *cancleButton = (UIButton *)subView;
                [cancleButton setTitle:@"hi" forState:UIControlStateNormal];
            }
        }
    
    }
    

    Before search started, in UISearchBarDelagate or UISearchDisplayControllerDelegate do:

    [self.searchDisplayController.searchBar.subviews enumerateObjectsUsingBlock:^(UIButton *subview, NSUInteger idx, BOOL *stop) {
                if ([subview isKindOfClass:[UIButton class]]) {
                    [subview setTitle:@"OK" forState:UIControlStateNormal];
                    *stop = YES;
                }
            }];
    

    If you just want to change the “Cancel” text to the same in your locale, the proper way I think is using localization. Here is how:

    1. open your project in the Finder, locate the en.lproj directory
    2. rename it to your locale, or duplicate it if you have to support multiple languages
    3. remove any file references it may have contained in Xcode (they should look red)
    4. drag the same files from Finder from the new directory to Xcode
    5. (not sure this is necessary) edit your Info.plist and add these lines:

      • Localization native development region: your region (for example: en)
      • Localizations: for example English

    Note: it does not work in Simulator, test it on the device!

    (Source: http://www.ibabbleon.com/iphone_app_localization.html)

    For iOS7, this works.

    -(void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller{
        self.searchDisplayController.searchBar.showsCancelButton = YES;
        UIButton *cancelButton;
        UIView *topView = self.searchDisplayController.searchBar.subviews[0];
        for (UIView *subView in topView.subviews) {
            if ([subView isKindOfClass:NSClassFromString(@"UINavigationButton")]) {
                cancelButton = (UIButton*)subView;
            }
        }
        if (cancelButton) {
          //Set the new title of the cancel button
            [cancelButton setTitle:@"YourTitle" forState:UIControlStateNormal];
        }
    }
    

    Refer to @Salih’s solution above, I used this code and work perfect! Just call the method setupAppearance in AppDelegate.m when app launching.

    - (void)setupAppearance
    {
       id appearance = nil;
    
       if (IOS9_OR_LATER) {
           appearance = [UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]];
       } else {
           appearance = [UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil];
       }
    
       [appearance setTitle:@"CANCEL"];
    }
    

    Chiming in with the code I used inside the UIKitUISearchResultsUpdating protocol method updateSearchResults(for searchController: UISearchController):

    if let cancelButton : UIButton = searchController.searchBar.value(forKey: "_cancelButton") as? UIButton {
        cancelButton.setTitle("Back", for: UIControlState.normal)
    }
    

    (iOS 10, Swift 3.0)