Is it best to use init(displayP3Red:green:blue:alpha:) by default with an availability check when creating a UIColor? Honestly I can't see the difference between the two so I'm not sure how much it matters, but I was hoping someone could shed some light on this.
if #available(iOS 10.0, *) {
self.init(displayP3Red: r, green: g, blue: b, alpha: a)
} else {
self.init(red: r, green: g, blue: b, alpha: a)
}
No, these calls are not equivalent. Passing the same RGBA values to each will result in different colors.
Here's a handy article discussing the differences in color spaces. It makes the nice analogy of a color space being like units of length on a ruler. If I say some object has a length of 1.0, that doesn't make any sense unless you know how long "1.0" is. Inches? Meters? Furlongs? Parsecs? The definition of the unit makes a huge difference to what the quantity in a measurement means.
Similarly, if I say a color has a red component of 1.0, that doesn't mean anything unless I also say how red 1.0 is. (Ditto for green and blue components.) For much of the history of web and app design, it was safe to assume that all measurements are relative to the sRGB standard — 1.0 red means "as red as sRGB can get".
But with the advent of phones, computers, TVs, etc, supporting much larger color gamuts that assumption is no longer safe. Display P3 is the color space used by newer Apple devices (and closely matches that used by newer 4K HDR TVs). P3 supports a broader range of colors than sRGB, meaning that "as red as sRGB can get" is not red enough.
To make it a little bit easier to interoperate between sRGB and P3 devices, Apple's APIs include an "Extended sRGB" color space. In regular sRGB, as in most color spaces, component values are restricted to the 0.0–1.0 range — that is, you can't have a red component of 1.1, and if you try, you'll just get it clamped down to 1.0. Extended sRGB is defined to be the same as sRGB for component values in the 0.0–1.0 range, but permits using values outside that range to express colors outside the sRGB gamut. (This is what the Apple documentation means when it says UIColor(red:green:blue:alpha:)
uses an extended sRGB color space.)
UIColor
(and CGColor
that sits below it) in iOS don't offer handy utilities for color space conversion, but NSColor
in macOS does, which makes it handy for illustrating the difference:
The first red is equivalent to UIColor(displayP3Red: 1, green: 0, blue: 0, alpha: 1)
in iOS. The second is equivalent to UIColor(red: 1, green: 0, blue: 0, alpha: 1)
in iOS. If you're viewing this answer on a P3 display*, you'll probably notice at least a subtle difference in the color swatches.
And down below, notice the converted values. "sRGB max red", aka UIColor(red: 1, green: 0, blue: 0, alpha: 1)
is roughly equivalent to (r: 0.918, g: 0.2, b: 0.139, a: 1)
in P3. "P3 max red", aka UIColor(displayP3Red: 1, green: 0, blue: 0, alpha: 1)
is outside sRGB, but can be expressed in "extended sRGB" as (r: 1.093, g: -0.227, b: -0.15, a: 1)
.
* Apple devices with P3 displays include iPhone 7, iPad Pro 2016, iMac fall 2015, MacBook Pro fall 2016, and later