Search code examples
iosobjective-cuisearchbaruiappearance

UISearchBar cancel button not styled if displayed before viewDidAppear


I'm setting the cancel button's tint like so:

[UIBarButtonItem appearance].tintColor = [UIColor highlightedTextColor];

And it works well if the cancel button is shown after or during viewDidAppear e.g. if Cancel is displayed when the search bar receives focus:

Cancel button properly styled

However if this is performed before, e.g. in viewDidLoad or even in viewWillAppear:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self.searchBar setShowsCancelButton:YES animated:NO];
}

Then the result isn't as nice:

Cancel not styled

The text is actually there, though only a very faint shadow can be detected with the Color Meter. Has anyone else encountered this problem and found a solution? The best one I could find is to show the cancel button in the viewDidAppear.


Solution

  • To me it works fine, I create UISearchBar inside a UIView. The viewDidLoad:

    - (void)viewDidLoad {
        [super viewDidLoad];
        _searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(10.0f, 0.0f, self.view.bounds.size.width-20, 44.0f)];
        _searchBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
        _searchBar.autoresizingMask = UIViewAutoresizingFlexibleHeight;
        _searchBar.showsCancelButton = YES;
        //_searchBar.searchBarStyle = UISearchBarStyleMinimal;
        [_searchBar sizeToFit];
        [_searchBar becomeFirstResponder];
        _searchBar.delegate = self;
        _searchBar.barTintColor = color;
        _searchBar.tintColor = color;
        [[UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
                                                                                                  [UIColor whiteColor],
                                                                                                  NSForegroundColorAttributeName,
                                                                                                  nil]
                                                                                        forState:UIControlStateNormal];
        _barWrapper = [[UIView alloc]initWithFrame:self.navigationController.navigationBar.bounds];
        [_barWrapper addSubview:_searchBar];
        _barWrapper.autoresizingMask = UIViewAutoresizingFlexibleWidth;
    }
    

    In viewWillAppear I put the barWrapper in the navigationbar.

    - (void)viewWillAppear:(BOOL)animated {
        [super viewWillAppear:animated];
        [self.navigationController.navigationBar addSubview:_barWrapper];
        [_searchBar becomeFirstResponder];
    }
    

    To finalize, in viewWillDisappear I remove the barWrapper from navigation bar.

    - (void)viewWillDisappear:(BOOL)animated{
        [_barWrapper removeFromSuperview];
    }