52

Has anyone any idea or code sample on how can I change the text color of the placeholder text of a UISearchBar?

DarkLeafyGreen
  • 69,338
  • 131
  • 383
  • 601
csotiriou
  • 5,653
  • 5
  • 36
  • 45
  • I think this post will help you http://stackoverflow.com/questions/1340224/iphone-uitextfield-change-placeholder-text-color – frankWhite Aug 06 '12 at 14:52
  • I have already looked at it. This post concerns a UITextfield. Subclassing a UITextfield and overriding the -drawPlaceholderInRect method would certainly help. However, UISearchBar is not a subclass of UITextfield, and as such, I can't override this method. – csotiriou Aug 06 '12 at 20:25
  • sorry, I don't know this. UISearchBar is subclass of UIView, and I think you can subclass from it and try override drawRect method, adding in it code from previous post. Maybe this help – frankWhite Aug 07 '12 at 06:27
  • For Swift 3. I found a solution here: [**Customize textfield easily**](http://stackoverflow.com/a/40105165/4593553) – Jerome Oct 18 '16 at 10:04

18 Answers18

82

for iOS5+ use the appearance proxy

[[UILabel appearanceWhenContainedIn:[UISearchBar class], nil] setTextColor:[UIColor redColor]];
Zayin Krige
  • 3,229
  • 1
  • 35
  • 34
  • Since my post I had found the answer, and indeed this is the best way to do it. Clean, simple and it doesn't break anything. – csotiriou Jul 02 '13 at 16:46
  • 10
    This is not really valid. UILabel doesn't support customization this way, because the `textColor` property of UILabel is not marked with `UI_APPEARANCE_SELECTOR` as required by the documentation. See also http://stackoverflow.com/questions/11839044/how-do-i-apply-uiappearance-proxy-properties-to-uilabel – Joshua J. McKinnon Jul 22 '13 at 02:23
  • This is working for me only if I add some placeholder in Stroyboard.. Directly setting placeholder through code doesnt work if we dont have some placeholder in the storyboard.. wired – sach Sep 12 '14 at 06:25
  • 7
    I gave this thing an up-vote by accident. It does not work well. People should use: http://stackoverflow.com/questions/1340224/iphone-uitextfield-change-placeholder-text-color – Katedral Pillon Sep 14 '14 at 19:52
  • this is not a valid answer, see my answer below – Boris Nikolic Nov 01 '15 at 18:27
31

Found the answer from Change UITextField's placeholder text color programmatically

// Get the instance of the UITextField of the search bar
UITextField *searchField = [searchBar valueForKey:@"_searchField"];

// Change search bar text color
searchField.textColor = [UIColor redColor];

// Change the search bar placeholder text color
[searchField setValue:[UIColor blueColor] forKeyPath:@"_placeholderLabel.textColor"];
Community
  • 1
  • 1
Wayne Liu
  • 1,172
  • 11
  • 23
21

First solution is OK, but if you use multiple UISearchBar, or create a lot of instances it may fail. The one solution that always work for me is to use also appearance proxy but directly on UITextField

   NSDictionary *placeholderAttributes = @{
                                            NSForegroundColorAttributeName: [UIColor darkButtonColor],
                                            NSFontAttributeName: [UIFont fontWithName:@"HelveticaNeue" size:15],
                                            };

    NSAttributedString *attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.searchBar.placeholder
                                                                                attributes:placeholderAttributes];

    [[UITextField appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setAttributedPlaceholder:attributedPlaceholder];
Emre YILMAZ
  • 152
  • 2
  • 10
Marcin Małysz
  • 733
  • 8
  • 12
  • 1
    It's the only solution that worked correctly for me, other solutions failed when navigating the viewController hierarchy back and forth, and destroying / recreating the search bar – DTs Dec 17 '16 at 22:46
  • This should be the accepted solution for ObjC/iOS 13 – Peter Suwara Jul 04 '20 at 11:13
18

Here is a Solution for Swift:

Swift 2

var textFieldInsideSearchBar = searchBar.valueForKey("searchField") as? UITextField
textFieldInsideSearchBar?.textColor = UIColor.whiteColor()

var textFieldInsideSearchBarLabel = textFieldInsideSearchBar!.valueForKey("placeholderLabel") as? UILabel
textFieldInsideSearchBarLabel?.textColor = UIColor.whiteColor()

Swift 3

let textFieldInsideSearchBar = searchBar.value(forKey: "searchField") as? UITextField
textFieldInsideSearchBar?.textColor = UIColor.white

let textFieldInsideSearchBarLabel = textFieldInsideSearchBar!.value(forKey: "placeholderLabel") as? UILabel
textFieldInsideSearchBarLabel?.textColor = UIColor.white
pableiros
  • 14,932
  • 12
  • 99
  • 105
derdida
  • 14,784
  • 16
  • 90
  • 139
11

Try this and see: (I tested below code with Swift 4.1 - Xcode 9.3-beta4)

@IBOutlet weak var sbSearchBar: UISearchBar!

if let textfield = sbSearchBar.value(forKey: "searchField") as? UITextField {

    textfield.backgroundColor = UIColor.yellow
    textfield.attributedPlaceholder = NSAttributedString(string: textfield.placeholder ?? "", attributes: [NSAttributedStringKey.foregroundColor : UIColor.red])

    textfield.textColor = UIColor.green

    if let leftView = textfield.leftView as? UIImageView {
        leftView.image = leftView.image?.withRenderingMode(.alwaysTemplate)
        leftView.tintColor = UIColor.red
    }
}

Here is result:

enter image description here

Krunal
  • 77,632
  • 48
  • 245
  • 261
  • 1
    That's awesome, but if that isn't documented how reliable do you think it is as an interface? I will use it if it doesn't get the app rejected and it's unlikely Apple will suddenly change it. (Don't see why they would) – clearlight Jun 28 '22 at 04:12
11

It is easy from iOS 13.0 onwards, You can simply use searchTextField property of a search bar to update attributed properties of the placeholder.

self.searchController.searchBar.searchTextField.attributedPlaceholder =  NSAttributedString.init(string: "Search anything...", attributes: [NSAttributedString.Key.foregroundColor:UIColor.red])

One line solution

Sucharu Hasija
  • 1,096
  • 11
  • 23
7
if let textFieldInsideSearchBar = searchBar.value(forKey: "searchField") as ? UITextField {
    textFieldInsideSearchBar ? .textColor = UIColor.white

    if let textFieldInsideSearchBarLabel = textFieldInsideSearchBar!.value(forKey: "placeholderLabel") as ? UILabel {
        textFieldInsideSearchBarLabel ? .textColor = UIColor.white

        if let clearButton = textFieldInsideSearchBar ? .value(forKey: "clearButton") as!UIButton {

            clearButton.setImage(clearButton.imageView ? .image ? .withRenderingMode(.alwaysTemplate),
                for : .normal)
            clearButton.tintColor = UIColor.white
        }
    }

    let glassIconView = textFieldInsideSearchBar ? .leftView as ? UIImageView

    glassIconView ? .image = glassIconView ? .image ? .withRenderingMode(.alwaysTemplate)
    glassIconView ? .tintColor = UIColor.white
}
DILIP KOSURI
  • 455
  • 5
  • 10
phitsch
  • 823
  • 13
  • 12
6

Swift 5 - ios 13:

Those who are stuck let me tell you it is going to work only in viewDidLayoutSubviews not in viewDidLoad

override func viewDidLayoutSubviews() {

    setupSearchBar(searchBar: YourSearchBar)

}

    func setupSearchBar(searchBar : UISearchBar) {

    searchBar.setPlaceholderTextColorTo(color: UIColor.white)        

   }

extension UISearchBar
{
    func setPlaceholderTextColorTo(color: UIColor)
    {
        let textFieldInsideSearchBar = self.value(forKey: "searchField") as? UITextField
        textFieldInsideSearchBar?.textColor = color
        let textFieldInsideSearchBarLabel = textFieldInsideSearchBar!.value(forKey: "placeholderLabel") as? UILabel
        textFieldInsideSearchBarLabel?.textColor = color
    }
}

Happy coding :)

rupesh45
  • 125
  • 2
  • 8
4

It looks like Apple does not want us to play with the placeholder colors when it comes to UISearchBar class. So, let's create our own placeholder label!

  • No subclassing.
  • Works with iOS 13 SDK.
  • Just one innocent workaround.

enter image description here

let searchBar = searchController.searchBar
// ...
// Configure `searchBar` if needed
// ...

let searchTextField: UITextField
if #available(iOS 13, *) {
    searchTextField = searchBar.searchTextField
} else {
    searchTextField = (searchBar.value(forKey: "searchField") as? UITextField) ?? UITextField()
}

// Since iOS 13 SDK, there is no accessor to get the placeholder label.
// This is the only workaround that might cause issued during the review.
if let systemPlaceholderLabel = searchTextField.value(forKey: "placeholderLabel") as? UILabel {
    // Empty or `nil` strings cause placeholder label to be hidden by the search bar
    searchBar.placeholder = " "

    // Create our own placeholder label
    let placeholderLabel = UILabel(frame: .zero)

    placeholderLabel.text = "Search"
    placeholderLabel.font = UIFont.systemFont(ofSize: 17.0, weight: .regular)
    placeholderLabel.textColor = UIColor.blue.withAlphaComponent(0.5)

    systemPlaceholderLabel.addSubview(placeholderLabel)

    // Layout label to be a "new" placeholder
    placeholderLabel.leadingAnchor.constraint(equalTo: systemPlaceholderLabel.leadingAnchor).isActive = true
    placeholderLabel.topAnchor.constraint(equalTo: systemPlaceholderLabel.topAnchor).isActive = true
    placeholderLabel.bottomAnchor.constraint(equalTo: systemPlaceholderLabel.bottomAnchor).isActive = true
    placeholderLabel.translatesAutoresizingMaskIntoConstraints = false
    placeholderLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
} else {
    searchBar.placeholder = ""
}
Yevhen Dubinin
  • 4,657
  • 3
  • 34
  • 57
3

Swift 3

UILabel.appearance(whenContainedInInstancesOf: [UISearchBar.self]).textColor = UIColor.white
Shoaib
  • 1,295
  • 15
  • 22
3

iOS 13

Previous solutions may not work on iOS 13 because new searchTextField has been added, and you can set attributed string on it.

I wrapped that into category:

@interface UISearchBar (AttributtedSetter)
- (void)setThemedPlaceholder:(NSString*)localizationKey;
@end

@implementation UISearchBar (AttributtedSetter)

- (void)setThemedPlaceholder:(NSString*)localizationKey {
    ThemeObject *currentTheme = [[ThemeManager standardThemeManager] currentTheme];
    self.searchTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:NSLocalizedString(localizationKey, @"") attributes:@{NSForegroundColorAttributeName : currentTheme.colorSearchBarText}];
}

@end
Martin Berger
  • 1,639
  • 3
  • 18
  • 39
  • I've tried assigning to `attributedPlaceholder` multiple times with no luck. It accepts the string contents, but does not change the text color. The search bar is inside a navigation item. – Andreas Feb 29 '20 at 10:40
3

iOS 13

Use a custom search bar subclass.

This also works when part of a UISearchController inside a UINavigationItem (with hidesSearchBarWhenScrolling = true).

We want to apply our changes immediately after UIAppearance proxies are being applied since those are the most likely root cause:

class MySearchBar : UISearchBar {
    // Appearance proxies are applied when a view is added to a view hierarchy, so apply your tweaks after that:
    override func didMoveToSuperview() {
        super.didMoveToSuperview() // important! - system colors will not apply correctly on ios 11-12 without this

        let placeholderColor = UIColor.white.withAlphaComponent(0.75)
        let placeholderAttributes = [NSAttributedString.Key.foregroundColor : placeholderColor]
        let attributedPlaceholder = NSAttributedString(string: "My custom placeholder", attributes: placeholderAttributes)
        self.searchTextField.attributedPlaceholder = attributedPlaceholder
        
        // Make the magnifying glass the same color
        (self.searchTextField.leftView as? UIImageView)?.tintColor = placeholderColor
    }
}

// Override `searchBar` as per the documentation
private class MySearchController : UISearchController {
    private lazy var customSearchBar = MySearchBar()
    override var searchBar: UISearchBar { customSearchBar }
}

That took quite some time to get working properly...

Andreas
  • 2,665
  • 2
  • 29
  • 38
3

worked for me on IOS 13

searchBar.searchTextField.attributedPlaceholder = NSAttributedString(
    string: "Search something blabla",
    attributes: [.foregroundColor: UIColor.red]
)
andrei
  • 1,353
  • 15
  • 24
2

Try this:

[self.searchBar setValue:[UIColor whatever] forKeyPath:@"_searchField._placeholderLabel.textColor"];

You can also set this in storyboard, select search bar, add entry under User Defined Runtime Attributes:

_searchField._placeholderLabel.textColor

of type Color and select the color you need.

Borzh
  • 5,069
  • 2
  • 48
  • 64
0

After surveyed a couple of answers, I come out this, hope its help

for (UIView *subview in searchBar.subviews) {
    for (UIView *sv in subview.subviews) {
        if ([NSStringFromClass([sv class]) isEqualToString:@"UISearchBarTextField"]) {

            if ([sv respondsToSelector:@selector(setAttributedPlaceholder:)]) {
                ((UITextField *)sv).attributedPlaceholder = [[NSAttributedString alloc] initWithString:searchBar.placeholder attributes:@{NSForegroundColorAttributeName: [UIColor whiteColor]}];
            }
            break;
        }
    }
}
Js Lim
  • 3,625
  • 6
  • 42
  • 80
  • I subclassed the UISearchBar class, and then I used an attributed placeholder like you did. But in my subclass, I added override var placeholder: String? { didSet { changePlaceholderColor(str: placeholder ?? "") } }, that way, whenever I change the placeholder text on this searchBar, it will automatically make the placeholder text the correct color. If I didn't do this, then it would override my placeholder color if I ever set a normal placeholder. – Daniel Jones Jan 29 '17 at 01:59
0

This solution works on Xcode 8.2.1. with Swift 3.0. :

extension UISearchBar
{
    func setPlaceholderTextColorTo(color: UIColor)
    {
        let textFieldInsideSearchBar = self.value(forKey: "searchField") as? UITextField
        textFieldInsideSearchBar?.textColor = color
        let textFieldInsideSearchBarLabel = textFieldInsideSearchBar!.value(forKey: "placeholderLabel") as? UILabel
        textFieldInsideSearchBarLabel?.textColor = color
    }
}

Usage example:

searchController.searchBar.setPlaceholderTextColorTo(color: mainColor)
Darkwonder
  • 1,149
  • 1
  • 13
  • 26
-1

This is an old question, but for anyone stumbling on it nowadays, you can change the search icon on iOS 8.x - 10.3 using the following:

[_searchBar setImage:[UIImage imageNamed:@"your-image-name"] forSearchBarIcon:UISearchBarIconSearch state:UIControlStateNormal];

Regarding the placeholder text color, you may check my other answer, which uses a Category, here: UISearchBar change placeholder color

m_katsifarakis
  • 1,777
  • 1
  • 21
  • 27
-3

Try this:

  UITextField *searchField = [searchbar valueForKey:@"_searchField"];
  field.textColor = [UIColor redColor]; //You can put any color here.
Ankit
  • 1,684
  • 14
  • 14
  • I don't want to change the color of the normal text. I want to change the color of the placeholder text. – csotiriou Aug 06 '12 at 14:08
  • 4
    This is NOT OK! You are accessing a PRIVATE iVAR when you do this and this might get your app rejected from app store. – Widerberg May 19 '14 at 11:06
  • @AlexanderW : If this was meant not to be used, you won't be able to access it... Everyone around the world use this thing for changing color of textfield placeholder color change.... my app has never been rejected due to this... but its just a solution, may not a perfect one..... – Ankit May 23 '14 at 09:54