Reputation: 379
After looking for updated (iOS 13) answers, I didn't find any solutions to this simple problem :
How to change the textColor
of the placeholder in an UISearchBar
?
My app doesn't handle Light/Dark
mode. I don't want the system to change my UIPlaceHolder
text color. I want it to be always white
.
if #available(iOS 13.0, *) {
let attrString = NSMutableAttributedString(string: "My PlaceHolder")
attrString.addAttributes([NSAttributedString.Key.foregroundColor: UIColor.white], range: NSRange(location: 0, length: attrString.length))
searchController.searchBar.searchTextField.attributedPlaceholder = attrString
}
I expected this code to work. I thought the new property searchTextField
would have made it easier to customize my UISearchBar
.
EDIT:
This code kind of works in the viewDidAppear
method :
if #available(iOS 13.0, *) {
searchController.searchBar.searchTextField.attributedPlaceholder = NSAttributedString(string: "My PlaceHolder", attributes: [NSAttributedString.Key.foregroundColor: UIColor.white.withAlphaComponent(0.80)])
}
The issue is that the color is changing when you scroll up and down.
Upvotes: 6
Views: 1902
Reputation: 11435
As you already mentioned, your code works only in viewDidAppear
, which makes the placeholder to flicker from the default gray color to the preferred color.
However, there seem to be a time before viewDidAppear
(I couldn't figure it out when exactly), to change the placeholder before the view actually appears.
I suppose, this may be connected to how iOS handles light/dark mode and/or an iOS bug.
The solution I came out with that works around the issue:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if #available(iOS 13.0, *) {
let placeholder = NSAttributedString(string: "Search",
attributes: [
.foregroundColor: UIColor.white
])
let searchTextField = searchBar.searchTextField
// Key workaround to be able to set attributedPlaceholder
DispatchQueue.global().async {
DispatchQueue.main.async {
searchTextField.attributedPlaceholder = placeholder
}
}
}
}
There seem to be no performance and/or other downside to this method.
If anybody else comes with a better approach, feel free to collaborate.
Upvotes: 3
Reputation: 994
I guess the reason why it doesn't work is probably the searchController.searchBar.searchTextField = nil
you got.
searchTextField
is a new property for iOS 13
, which can be done if you only support >= iOS 13
. If you want to adapt to the previous version of iOS 13
, you can traverse UISearchBar
to find UISearchBarTextField
and directly set the found UISearchBarTextField
.
The code I looked up is probably like this, I put it in the Category
of UIView
.
- (UIView *)findChildViewClass:(Class)childViewClass fromView:(UIView *)fromView{
for (UIView *subView in fromView.subviews) {
if ([subView isMemberOfClass:childViewClass]) {
return subView;
}
UIView *finalView = [self findChildViewClass:childViewClass fromView:subView];
if (finalView) {
return finalView;
}else{
continue;
}
}
return nil;
}
When used, you can customize a searchTextField
property to inherit from UITextField
to save the found value.
_searchTextField = (UITextField *)[searchBar findChildViewClass:NSClassFromString(@"UISearchBarTextField") fromView: searchBar];
This is what I use now, it is working, I hope to be useful to you.
Upvotes: 0
Reputation: 726
you can set this with UITextField
appearance
property. check this line of code
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).defaultTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
Upvotes: 0