iOS7 UILabel to adopt same tintColor as window

zanona picture zanona · Oct 1, 2013 · Viewed 7.2k times · Source

I know that for elements of classes UIButton and UIBarButtonItem they automatically assume window.tintColor as the main colour, which results of an immediate change in case I set a new tintColor to window at any time in the app.

I was wondering if there is any way to make UILabel elements to follow the same pattern, where once created they automatically assumer its default colour as window.tintColor and if changing window.tintColor at any time within my app runtime would also result in changing the UILabel tintColour automatically?

I hope that makes sense.

Answer

redlightbulb picture redlightbulb · Oct 9, 2013

UILabels are a subclass of UIView, so when you are running in iOS 7 they will have a tintColor property and will inherit that color from their parent view if their tint color is set to nil (which is default).

From Apple's Documentation:

By default, a view’s tint color is nil, which means that the view uses its parent’s tint. It also means that when you ask a view for its tint color, it always returns a color value, even if you haven’t set one.

However, you also ask "if changing window.tintColor at any time within my app runtime would also result in changing the UILabel tintColour automatically?" Apple advises you to not change the tint color when items are on screen:

In general, it’s best to change a view’s tint color while the view is offscreen.

I would guess this is because there is no guarentee that all the various UI elements will detect the tintColor change and update their visible views. However, the UIView documentation suggests a workaround if you want to update tintColor while your UILables are on screen:

To refresh subview rendering when this property changes, override the tintColorDidChange method.

So just make sure to call tintColorDidChange on any views currently on screen whose tint color should update when the tintColor of their parent view changes.

But why don't your UILabel's update their color?

So the above helps you set and update your various tintColor's, but you're not seeing any effect - why?

Well that has to do with what Apple designed Tint to indicate. From the Human Interface Guidelines:

color gives users a strong visual indicator of interactivity

Apple got rid of borders and gradients around interactive elements and replaced them with color - specifically tintColor. The whole idea behind tintColor is that things users can tap on get it, and things they can't tap on don't.

UILabel is not an interactive element - it is a text description - and so Apple will let you set a tintColor on it (as any UIView has a tintColor) but setting that tintColor will not change how it is drawn.

So what should you do? First, be aware that making more than just buttons take on the tint color could be a poor UI choice for your app - iOS 7 users and Apple app reviewers both will be expecting those rules to be followed.

So are you forced to keep your UILabel free from color then?

No - especially if you do things "right". Apple explains:

In a content area, add a button border or background only if necessary. Buttons in bars, action sheets, and alerts don’t need borders because users know that most of the items in these areas are interactive. In a content area, on the other hand, a button might need a border or a background to distinguish it from the rest of the content.

I would suggest you consider the UI of your app. If you really want your non-intereactive elements to have the same tintColor as your interactive elements, then make sure you use something more, like a border or background color, so your users (and Apple app reviewers) know what is clickable and what is not.

As to how you should update the colors, you can either manually set the textColor property to be whatever color you want, or you'll need to make your own subclass of UILabel that overrides - (void)tintColorDidChange to update the textColor property when notifications are sent out - allowing you to have a UILabel whose text updates to match the tintColor of its parent.

I hope this helps!