Working efficiently with colors in Xcode

Hello there!

It’s been a while since I shared Getting the right colors in your iOS app, a blogpost I wrote for helping iOS devs prevent the color nightmare that happens every now and then. That blogpost was cool and got more visits than I expected, but, the information I exposed at that moment was neither complete nor certainly accurate, and it got outdated very quickly too. My appologies for taking too long to write about it again.

Today, I bring this update in order to help the iOS community once more, because, I found that there aren’t much articles out there that involve all the required information that one needs in order not to fail miserably when working with colors in Xcode.

After lots of research, information gathering, experiments, insights, and conclusions, I feel prepared to dive in to the colors world again. So, here we go…

How do I set the right color?

First things first. There are two ways of setting a color for a UI component in Xcode:

  • Interface Builder
  • Programmatically

No matter which one you use, the point is that, you need to make sure you obtain the same exact color in either case, even more if you consider that it’s very likely you’ll need to use both methods at some point in your project. Consistency is key.

It turns out that when you create a color programmatically, by calling UIColor(red:green:blue:alpha:), Xcode will create a color using the sRGB IEC 61966-2-1 color space (more on color spaces later). Given that case, whenever you are setting a color through Interface Builder, you must ensure that it's being created with that same color space too, so that, the color is exactly the same.

This is, given this code…

let myCustomColor = UIColor(red: 38/255.0, green: 49/255.0, blue: 197/255.0, alpha: 1.0) // sRGB

…you should make sure that you set the same RGBA values and you use the same color space when in Interface Builder…

You can quickly verify that the colors are the same by doing this simple experiment:

  1. Put a view inside a view
  2. Set the outer view’s color programmatically
  3. Set the inner view’s color via Interface Builder, using the same RGBA values, and selecting the sRGB color space
  4. Build & Run, and check out the outcome
If you use UIColor(red:green:blue:alpha:) in your code, and you select sRGB when in Interface Builder, using the same RGBA values, the colors will match.

Well done! This is half of the process of being consistent, and it might have already solved your issues. However, in order to guarantee that the colors in your app match the UI designs you are supposed to follow, you must also make sure that the color you’ve picked is the one you’re supposed to use, and this is the hardest part, which I’ll cover in the next section.

How do I pick the right color?

Extracting the RGBA components of a color can be a cumbersome task, and this could be mostly because of a lack of understanding of how color spaces work. Long story short, I will try to summarize this complex world as best as possible.

In order to represent a color, two components are required:

  1. Values
  2. A color space, in which the color is represented ← This is what most people don’t know

On to the values, there are several models to depict them:

  • RGBA (Red, Green, Blue, Alpha) ← the one we mostly use in Xcode
  • HSV (Hue, Saturation, Value)
  • HSL (Hue, Saturation, Lightness)
  • And more…

These different models are just bells and whistles to work more comfortably when creating colors through UI sliders or fancy wheels, and I won’t get into detail here, since you’ll encounter yourself copying RGBA values about 99,99% of the time. It doesn’t matter whether you use 0–255 integer notation, 0–1 floating point notation, or Hex notation; it’s all the same as long as you do the maths well.

Now let’s talk about color spaces, which is where it does get complex…

Color Spaces

What’s a color space, anyway? Do I even need to care? The answer is yes, at least a bit.

A color space is a component that defines which range of colors can be represented through the notations we mentioned above.

The human eye can see plenty of colors. In fact, it can see way more colors than what most screens can actually expose. This is because the hardware that screens use is somehow limited, and in consequence they work with restricted color spaces (at least more limited than what the human eye can see).

Different screens represent colors through different color spaces, depending on the device’s hardware.

If you click here you’ll see an image that contains a logo, which you’ll only distinguish if your display works with a P3 color space (otherwise, you’ll see a boring rectangle filled with just one reddish color).

Now that you understand what color spaces are, let’s explore the issues that they carry…

How color spaces fit into RGBA values

Let’s suppose we are using the RGBA notation to write down a color. With this notation, and a depth of 8 bits per channel, you can represent up to 255 x 255 x 255 colors = 16,581,375 (the famous 16 million colors) and even more, when you combine them with the alpha component (x 255 again) you’ll get up to more than 4 billion (also known as true color). That is the amount of colors you can represent using this notation, and notice that this value is fixed. It doesn’t matter whether you choose a bigger or smaller color space to work with: You cannot represent more than that number of colors in RGBA. Imagine this as having a fixed number of 4,228,250,625 slots: Any color you want to represent must fall into one of these slots. Notice this: You won’t necessarily get a bigger number of colors by using a bigger color space, because there is a limit on how many colors you can write down. What changes, however, is that when working on a bigger color space, the variation between two consecutive values (for instance: #A0A0A0 and #A0A0A1) is more noticeable to the eye. This happens because when using a bigger color space, more actual colors have to fit within the same amount of fixed slots. Besides, when in a bigger color space, the values on the extremes will represent more vivid colors (e.g. #FF0000 in P3 is a much more vivid red than #FF00000 in sRGB). It's because of these observable changes that you probably get headaches when not getting the exact color you want: Maybe you are just obtaining their RGBA values from one color space, and generating them in Xcode using a different color space. If the color spaces mismatch, you will get incorrect colors in your app, in spite of having replicated the same RGBA values.

Now that you know that color space matters, you must make sure that you pick colors from the proper color space. This is, if you are using sRGB to represent a color in your app, you must pick colors from a sRGB color space, and just replicate the same RGBA values in Xcode. This sounds a lot simpler than it really is. The million dollar question is, how do you pick a color from a sRGB space?

Getting the right RGBA values

Photoshop

If you are cropping your assets right away from a PSD file, then it’s a piece of cake: You just open it in Photoshop and use the eyedropper tool to get the RGB values. This way, you will get RGB values with a full alpha component (A = 1). If you want to be more thorough, you can check out the individual layer components (for instance, a color overlay) and take the exact RGB and Alpha values (transparencies might play an important role in your app’s design). But, be aware: The PSD file must be opened using the sRGB color space as its working space. You can check that out by going to Edit > Color Settings. If it’s not using sRGB, you will need to convert the file to that profile, and it’s highly suggested that you warn the designers to use sRGB profiles when creating assets for mobile apps.

I have to admit that I used to ignore these alerts…

There is another option, though. You can get the color from a different profile, say Adobe RGB for instance (which is bigger than sRGB), and generate the colors in Xcode by always using the Adobe RGB color space, both via Interface Builder (by selecting it from the dropdown menu) and via code (by using a different function to generate the color, other than the conventional UIColor(red:green:blue:alpha:) that I mentioned above - you can check out the official documentation on how to do that). However, sRGB is the standard that most applications use (e.g. web navigators, Sketch, Zeplin, etc, not to mention Xcode itself too), that's why I highly recommend sticking to this one.

Other Design Apps

If you are getting your assets from tools like Sketch or Zeplin, you can get the RGBA values straight from there, without even needing an eyedropper tool. These values are represented in the sRGB color space.

Digital Color Meter

Another simpler approach to extract RGB values is to use an eyedropper tool from your Mac. There is the native Digital Color Meter app that can do that. The problem with this one is that, if your iOS app needs to use a bigger color space than the one that your display works with (for instance: you are using P3 for your app, but your Mac’s display is limited to sRGB), then the eyedropper won’t catch those P3 colors that your sRGB display cannot represent. To prove that, you can check out this image, and use Digital Color Meter to extract its RGB values while working in a sRGB display. You’ll always get the same RGB values across the whole image. On the other hand, if you open it in Photoshop (using P3 as working color space), and use the eyedropper tool, you’ll realize that there are two different colors in the image, even though you won’t be able to distinguish them through your sRGB display. I have discovered this through lots of try-and-error-like experiments. Another issue with Digital Color Meter is that you have to make sure that the image is opened with an app that takes into account its embedded color profile. Preview app works well for this purpose. Another experiment led me to realize that picking a color from an image opened in Preview vs. picking the same color straight from Finder’s carousel preview (which does not embed the profile) lead to different RGB values.

What about image assets?

Besides picking individual colors properly, you must make sure to pick files properly too when working with entire images. As stated by the official documentation,

Apply color profiles to your images. The default color space on iOS is Standard RGB (sRGB). To ensure that colors are correctly matched to this color space, make sure your images include embedded color profiles.

To know which color profile is embedded into an specific image, right-click the file and check it out under Get Info. To embed the image into a different color profile, you can use tools like Photoshop.

Shouldn't I work with P3?

Now you might wonder, if the newest devices can display P3, why should I stick to sRGB? Well, the truth is that if you work in a computer that has an sRGB display but you need to cover P3 colors, you’re going to have a hard time. Currently, almost at the end of 2017, most designers still work with sRGB displays. This is, they won’t be able to get the best out of their assets if they work with a bigger color space than what they can actually see on their screens.

Apple recommends to use the P3 color space only in specific situations, such as for UI components that can enhance the user experience by standing out through more intense colors, or for entire pictures that need to be more vivid. This WWDC session has a great insight on when to use P3.

The transition hasn’t been done yet, and again, sRGB is still the standard today, so, that’s the choice you should go for in most of cases.

TL;DR

As you might have noticed, working with colors may look like a very straightforward thing, but it isn’t, at all.

Nevertheless, it’s just a matter of consistency. My suggestions to keep this process as simple as possible are:

  1. Let the UI designers know that you are going to work with the sRGB color space. Suggest them to use the sRGB color profile for mobile apps. Make sure the PSD files you use to crop images have sRGB as working space, and the PNG images you use in your assets catalog have the sRGB color profile embedded.
  2. Use UIColor(red:green:blue:alpha:) for creating colors programmatically.
  3. Make sure the sRGB option is selected in the Interface Builder’s color picker dropdown menu each time you set a color this way.
  4. Work efficiently: Stick to one source of truth.

Bonus Track: The One Source of Truth

I’ve been wondering for years how it was possible that there hadn’t been a way to refer to the same thing when getting a color from the code vs. from Interface Builder. How come I have to write these RGBA values twice for the same color? I mean, one time in my code, and another time in Interface Builder’s color picker. Not only this is an obvious pain in the neck, but it also leads to problems because of breaking the DRY principle.

Good news, as of Xcode 9, you can create a color specifying it only once, by using Color Assets.

You can get your custom color either from Interface Builder or from the code, referring in both cases to the same thing.

I got mind blown when I saw this tool for the first time, as not only it prevents you from writing things twice, but also organizes your app’s colors in such a way that is very convenient for everyone to use. Honestly, I shouldn’t have been that surprised, as this kind of utility should have existed from long, long time ago.

Bad news, this tool is only compatible as of iOS 11. So, if your app has to support older iOS versions, you will need to write this kind of code:

let lime: UIColor
if #available(iOS 11.0, *) {
lime = UIColor(named: "Lime")!
} else {
lime = UIColor(red: 222/255.0, green: 254/255.0, blue: 50/255.0, alpha: 1.0)
}

…That’s bad.

Resources

I hope I’ve just covered this topic well and I made it understandable using the right words. There is a lot more detail to dive in. I will be happy to see your comments and experiences!

Here is a list with some of the resources I’ve used during my research. They could be useful for you too:

Happy coloring!

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.