14

I understand that this question has been asked many, many times on SO. However, as Apple does best, with the release of iOS 11, they seem to have made a seemingly unnecessary change to the UISearchBar, specifically it's view hierarchy.

In further, the "text field" of a search bar is no longer accessible in the search bar's subviews, causing all of the previous solutions to "access" and change the background color of the text field, or any property of the text field for that matter.

  • Does anyone know how to actually adjust the background color of a search bar in iOS 11?

FYI: I am specifically talking about the color behind the text... which now as of 11 defaults to white unless you specify the search bar style to be minimal.

UPDATE 1:

Since my posting of this question, I still have not found a valid or really any real solution to this issue. The closest I have seem to come is to dive deep into the appearance for instance properties

[[UISearchBar class] appearanceWhenContainedInInstancesOfClasses:(nonnull NSArray<Class<UIAppearanceContainer>> *)]

of the UISearchBar. Playing around with the found UITextField via methods such as the following:

if ([view isKindOfClass:[UITextField class]]) {
    return (UITextField*)view;
}
UITextField *searchTextField;
for (UIView *subview in view.subviews) {
    searchTextField = [self searchViewForTextFieldBg:subview];
    if (searchTextField) {
        break;
    }
}
return searchTextField;

you can begin drawing a new background view to be placed behind the view. However, the issues I had found too tedious to pursue further were drawing the a view with the correct frame / bounds to mimic exactly the original background.

Hopefully someone can find the actual solution to this problem. Nice miss apple...

Krunal
  • 77,632
  • 48
  • 245
  • 261
Will Von Ullrich
  • 2,129
  • 2
  • 15
  • 42
  • Have you tried UIView.appearance(whenContainedIn: UISearchBar)? Just an idea – Oscar Apeland Sep 27 '17 at 09:08
  • Have you seen this Q&A? https://stackoverflow.com/a/46010398/968219 – zgosalvez Sep 27 '17 at 14:07
  • @OscarApeland yes, tried many things including appearanceWhenCont... but nothing.. – Will Von Ullrich Sep 27 '17 at 17:17
  • 1
    @zgosalvez yes, but to override the white background that answer suggests `let textfield = scb.value(forKey: "searchField") as? UITextField` which I believe is against Apple's t&c since that's technically accessing a private API no? – Will Von Ullrich Sep 27 '17 at 17:18
  • 1
    @WillVonUllrich This isn't strictly disallowed, but it's unsafe as iOS updates can break undocumented features. It might be counted as using private APIs as well, but I've had an app in production with that exact hack without problems. – Oscar Apeland Sep 28 '17 at 07:44
  • Gotcha - good to know you have a prod app with this, but ... is there really no other way to do this? lol pretty sad – Will Von Ullrich Sep 28 '17 at 13:48
  • how can apple release an ios version where it is impossible to set the bar tint color.... – hhanesand Oct 02 '17 at 22:01

5 Answers5

17

I think you may be looking for this, right? But I've it in Swift :(

@IBOutlet weak var sbSearchBar: UISearchBar!

if let textfield = sbSearchBar.value(forKey: "searchField") as? UITextField {
    textfield.textColor = UIColor.blue
    textfield.backgroundColor = UIColor.yellow
}

Here is result:

enter image description here

Krunal
  • 77,632
  • 48
  • 245
  • 261
  • 2
    This will work you're right - I was more or less hoping for a solution relative to apples non-private api's. Of course this *does* work, it's just frowned upon as it runs the risk of failing at any point in the future from an update from apple – Will Von Ullrich Jan 11 '18 at 13:41
  • This worked for text color but not background color – drewster Mar 11 '19 at 15:15
10

This Swift code changes the background color of the text field:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        
    // background color of text field
    UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).backgroundColor = .cyan        
}

This is the result

example used to change the background to cyan color

pkamb
  • 33,281
  • 23
  • 160
  • 191
Maruta
  • 1,063
  • 11
  • 24
7
let searchBar = UISearchBar(frame: CGRect())
let searchField: UITextField? = searchBar.value(forKey: "searchField") as? UITextField
let searchBarBackground: UIView? = searchBar.value(forKey: "background") as? UIView
// searchBarBackground?.removeFromSuperview()

if searchField != nil {
    var frame = searchField?.frame
    frame?.size.height = 30
    searchField?.frame = frame!
    searchField?.backgroundColor = .yellow
}

searchBar.barTintColor = .red
searchBar.delegate = self
searchBar.backgroundColor = .green

Runtime Views Hierarchy

If we set background colors for UISearchBar with code above, we'll see the colored subviews as follow images(click links to see). 

backgroundColor for Superview of UISearchBar subviews

We can see the Class Name of green view is UISearchBar in Object inspector.

So, if we use searchBar.backgroundColor = .green, we'll set the backgroundColor of Superview green. Therefore, the UISearchBar instance property backgroundColor will set the superview's background color.

Superview of UISearchBar

barTintColor for UISearchBarBackground

We can see the Class Name of red view is UISearchBarBackground in Object inspector.

However, there's no direct method to access the view, we can use KVC searchBar.value(forKey: "background") as? UIView try to get searchBarBackground.

If we use searchBar.barTintColor = .red, we'll set the backgroundColor of UISearchBarBackground's view red. In order to remove two black border on the tint bar layer, we have to remove the background from superview.

barTintColor of UISearchBar

searchField?.backgroundColor for UITextField

We can see the Class Name of yellow view is _UISearchBarSearchFieldBackgroundView (Subview of UISearchBarTextField) in Object inspector.

There's no direct method to access the searchField, same as searchBarBackground. We can also use KVC searchField: UITextField? = searchBar.value(forKey: "searchField") as? UITextField try to get searchField.

If we use searchField?.backgroundColor = .yellow, we'll set the backgroundColor of UITextField yellow. Therefore, if we want to set text field background color, we have to access the searchField with KVC first

UITextField of UISearchBar

user5533269
  • 101
  • 1
  • 4
  • Welcome to Stack Overflow, please explain how this code would help the OP. – Daniel Feb 01 '18 at 14:56
  • 1
    Sorry, it’s my first time to answer question on stackoverflow and I am inexperienced about it , so I haven’t written why it works. I will capture the hierarchy of my App during debug runtime and explain how it helps tomorrow. : ) — ignore my English grammatical errors ,from a Chinese girl thanks~ 囧 – user5533269 Feb 02 '18 at 16:55
4

It's much simpler than that in Swift 5.

    searchBar.barTintColor = .black
    searchBar.searchTextField.backgroundColor = .white
Raz
  • 109
  • 8
2

Swift 4-5

searchController.searchBar.barTintColor = .white

Juan Rangel
  • 1,763
  • 1
  • 18
  • 34