UISearchBar text color change in iOS 7

Ios7Uisearchbar

Ios7 Problem Overview


How to change text color of UISearchBar in iOS 7?

In iOS 6, I was subclassing the UISearchBar and in layoutSubviews customising the properties of UITextField subview of UISearchBar.

But in iOS 7, UISearchBar doesn't have UITextField as its subview. How to fix this?

Ios7 Solutions


Solution 1 - Ios7

In iOS 7 to access Text Field you have to reiterate on level more. Change your code like this

for (UIView *subView in self.searchBar.subviews)
{
    for (UIView *secondLevelSubview in subView.subviews){
        if ([secondLevelSubview isKindOfClass:[UITextField class]])
        {
            UITextField *searchBarTextField = (UITextField *)secondLevelSubview;
            
            //set font color here
            searchBarTextField.textColor = [UIColor blackColor];
            
            break;
        }
    }
}

Note : This is Not Public API

OR

You can use appearance Property of UIControls, Like

[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setDefaultTextAttributes:@{NSForegroundColorAttributeName:[UIColor redColor]}];

Note: Appearance proxy can be used for iOS 9.0+ OutPut

enter image description here

You can set The tintcolor to apply to key elements in the search bar.

Use tintColor to tint foreground elements.

Use barTintColor to tint the bar background.

In iOS v7.0, all subclasses of UIView derive their behavior for tintColor from the base class. See the discussion of tintColor at the UIView level for more information. Apple Doc

Solution 2 - Ios7

You can set the text colour by

[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setTextColor:[UIColor blueColor]];

Solution 3 - Ios7

For XCode 6 (iOS8 SDK) the following DOESN'T work

[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setTextColor:[UIColor redColor]];

But the following DOES work (for deployment to iOS7 and iOS8)

[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setDefaultTextAttributes:@{NSForegroundColorAttributeName:[UIColor redColor]}];

Solution 4 - Ios7

While it's true that the UIAppearance protocol is a "public API," it's not true that UITextField supports this.

If you take a look at UITextField.h and look for the string "UI_APPEARANCE_SELECTOR" you'll see that it has no instances of this string. If you look at UIButton, you find quite a few - these are all of the properties that are officially supported by the UIAppearance API. It's somewhat well-known that UITextField is not supported by the UIAppearance API, so the code in Sandeep's answer will not always work and it's actually not the best approach.

This is a useful post with useful links: http://forums.xamarin.com/discussion/175/uitextfield-appearance

The correct approach is unfortunately messy - iterate through the subviews (or subviews of main subview for iOS7) and set it manually. Otherwise you will have unreliable results. But you can just create a category for UISearchBar and add a setTextColor:(UIColor*)color method. Example:

- (void)setTextColor:(UIColor*)color
{
    for (UIView *v in self.subviews)
    {
        if([Environment isVersion7OrHigher]) //checks UIDevice#systemVersion               
        {
            for(id subview in v.subviews)
            {
                if ([subview isKindOfClass:[UITextField class]])
                {
                    ((UITextField *)subview).textColor = color;
                }
            }
        }
    
        else
        {
            if ([v isKindOfClass:[UITextField class]])
            {
                ((UITextField *)v).textColor = color;
            }
        }
    }
}

Solution 5 - Ios7

Caution : This should lead to App Rejection!

KVC FTW. This did it for me.

UITextField *searchField = [self.searchBar valueForKey:@"_searchField"];
searchField.textColor = [UIColor redColor];

Solution 6 - Ios7

You can set the text attributes like so

[[UITextField appearanceWhenContainedIn:[<YOUR_CONTROLLER_NAME> class], nil] setDefaultTextAttributes:@{NSForegroundColorAttributeName:[UIColor whiteColor], NSFontAttributeName:[UIFont systemFontOfSize:14.0]}];

Solution 7 - Ios7

Here is working example done in C# using Xamarin:

SearchBar = new UISearchBar ();
foreach (var subView in SearchBar.Subviews) {
	foreach (var field in subView.Subviews) {
		if (field is UITextField) {
			UITextField textField = (UITextField)field;
			textField.TextColor = UIColor.White;
		}
	}
}

Hope this helps someone.

Solution 8 - Ios7

This seems to be the correct answer https://stackoverflow.com/a/19315895/2493073

The Swift version of it is:

UITextField.appearanceWhenContainedInInstancesOfClasses([UISearchBar.self]).textColor = UIColor.blueColor()

This would only work for iOS 9.0, in order to make it work for lower versions you'll need to follow this question. https://stackoverflow.com/a/27807417/2493073

Solution 9 - Ios7

Swift Extension

public extension UISearchBar {
    
    public func setTextColor(color: UIColor) {
        let svs = subviews.flatMap { $0.subviews }
        guard let tf = (svs.filter { $0 is UITextField }).first as? UITextField else { return }
        tf.textColor = color
    }
}

Solution 10 - Ios7

In my case, I have multiple UISearchBar objects and they need to change the textField font color. The appearanceWhenContainedIn update one UISearchBar behavior, but another doesn't.

I subclass the UISearchBar and implement custom -(id)initWithFrame: as following, and it works.

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.searchBarStyle       = UISearchBarStyleMinimal;
        self.tintColor            = [UIColor whiteColor];
        self.barTintColor         = [UIColor whiteColor];
        
        [[UITextField appearanceForTraitCollection:self.traitCollection whenContainedIn:[self class], nil] setDefaultTextAttributes:
         @{
           NSForegroundColorAttributeName : [UIColor whiteColor]
           }];
    }
    return self;
}

UIAppearance Protocol Reference said that,

> In other words, the containment statement in > appearanceWhenContainedIn: is treated as a partial ordering. Given a > concrete ordering (actual subview hierarchy), UIKit selects the > partial ordering that is the first unique match when reading the > actual hierarchy from the window down.

So, appearanceWhenContainedIn: won't deal with all UISearchBar in the hierachy of UIWindow. And it suggests that.

> Use the appearanceForTraitCollection: and > appearanceForTraitCollection:whenContainedIn: methods to retrieve the > proxy for a class with the specified trait collection.

Solution 11 - Ios7

The easiest way to do it is by putting this code in viewDidAppear or viewWillAppear:

[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setDefaultTextAttributes:@{NSForegroundColorAttributeName:[UIColor whiteColor]}];

This works in iOS 8 and Xcode 6, unlike some of the other code. It can mess around with the font and text size, etc, but you can change that in the text attributes.

That changes the text colour for all search bars in your app. If you only want to change one, use the above code, and then in any other views with a search bar, use the same code but set the colour to whatever you want.

Solution 12 - Ios7

you can use search bar inside textfield

 UISearchBar *  searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 50, 320, 44) ];
searchBar.autocorrectionType = UITextAutocapitalizationTypeWords;
searchBar.delegate = self;
searchBar.searchBarStyle = UISearchBarStyleMinimal;
searchBar.barTintColor = [UIColor redColor];
[[UITextField appearanceWhenContainedIn:[searchBar class], nil]setDefaultTextAttributes:@{NSForegroundColorAttributeName:[UIColor whiteColor]}];
[self.view addSubview:searchBar];

Solution 13 - Ios7

Update in Swift 3

UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).textColor = UIColor.black

Solution 14 - Ios7

Even though I would have preferred to use appearance API, it didn't work with iOS8. Here's the least hackish solution I did come with:

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    
    if (self.shouldEnableSearchBar)
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^
        {
            UITextField *searchBarTextField = [[AFPBaseViewController findSubviewsOfView:self.searchBar ofClass:[UITextField class]] firstObject];
            searchBarTextField.textColor = AFPConstantsColorGold;
        });
    }
    
}

You could maybe even create a UIView category with this. The reason why this has to be called in viewDidAppear is that UISearchBar is actually contained in a ViewController, and doesn't load all its subviews until it has appeared on screen. It could be added into viewWillAppear too, but I haven't tested it.

+ (NSArray *)findSubviewsOfView:(UIView *)view ofClass:(Class)class
{
    NSMutableArray *targetSubviews = [NSMutableArray new];
    for (id subview in view.subviews)
    {
        if ([subview isKindOfClass:class])
        {
            [targetSubviews addObject:subview];
        }
        
        if ([subview subviews].count)
        {
            [targetSubviews addObjectsFromArray:[self findSubviewsOfView:subview ofClass:class]];
        }
    }
    return targetSubviews.copy;
}

Solution 15 - Ios7

This is the right solution for iOS8:

[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setDefaultTextAttributes:@{NSFontAttributeName: [UIFont fontWithName:@"Helvetica" size:14], NSForegroundColorAttributeName:[UIColor lightGrayColor]}];

You have to set the font as well, otherwise, the font size will be wrong.

Solution 16 - Ios7

This class will give you full control over every item in the UISearchBar


import UIKit

class SMTSearchBar: UISearchBar {

    override init(frame: CGRect) {
        super.init(frame: frame)
        initialize()
    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
        initialize()
    }

    convenience init() {
        self.init(frame: CGRectZero)
        initialize()
    }

    // Style the view
    func initialize() {
    
        // Search Area
        let searchField = valueForKey("searchField") as! UITextField
        searchField.textColor = Colors.White
        searchField.font = UIFont(name: Fonts.MuseoSans500, size: 16)
        searchField.backgroundColor = Colors.Black.colorWithAlphaComponent(0.1)
    
        // Icons
        let searchIcon = UIImage(named: Icons.Search)?.imageWithTint(Colors.White)
        let smallClearIconNormal = UIImage(named: Icons.SmallClear)?.imageWithTint(Colors.White)
        let smallClearIconHighLight = UIImage(named: Icons.SmallClear)?.imageWithTint(Colors.White.colorWithAlphaComponent(0.5))
        setImage(searchIcon, forSearchBarIcon: .Search, state: .Normal)
        setImage(smallClearIconHighLight, forSearchBarIcon: .Clear, state: .Highlighted)
        setImage(smallClearIconNormal, forSearchBarIcon: .Clear, state: .Normal)
    }

    func setPlaceHolder(placeholder: String) {
        for subView in subviews{
            for subsubView in subView.subviews {
                if let textField = subsubView as? UITextField {
                    textField.attributedPlaceholder = NSAttributedString(string: placeholder, attributes: [NSForegroundColorAttributeName: Colors.White.colorWithAlphaComponent(0.5)])
                }
            }
        }
    }
}

Usage (in navigation bar)

let searchBar:SMTSearchBar = SMTSearchBar()
searchBar.sizeToFit()
searchBar.setPlaceHolder("Search for cool things")
navigationItem.titleView = searchBar
searchBar.becomeFirstResponder()

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGaurangView Question on Stackoverflow
Solution 1 - Ios7Toseef KhiljiView Answer on Stackoverflow
Solution 2 - Ios7SandeepMView Answer on Stackoverflow
Solution 3 - Ios7Graham DawsonView Answer on Stackoverflow
Solution 4 - Ios7Jordan SnyderView Answer on Stackoverflow
Solution 5 - Ios7Matthieu RieglerView Answer on Stackoverflow
Solution 6 - Ios7mOpView Answer on Stackoverflow
Solution 7 - Ios7Robert LawsonView Answer on Stackoverflow
Solution 8 - Ios7Fernando MataView Answer on Stackoverflow
Solution 9 - Ios7Adam WaiteView Answer on Stackoverflow
Solution 10 - Ios7AechoLiuView Answer on Stackoverflow
Solution 11 - Ios7Jack SolomonView Answer on Stackoverflow
Solution 12 - Ios7ShanmugasundharamView Answer on Stackoverflow
Solution 13 - Ios7BenView Answer on Stackoverflow
Solution 14 - Ios7mmackhView Answer on Stackoverflow
Solution 15 - Ios7MariusView Answer on Stackoverflow
Solution 16 - Ios7MichaelView Answer on Stackoverflow