I'm passing an RGB color to shapeLayer.fillColor
and shapeLayer.strokeColor
, and my code is crashing. Here's what I tried:
let shapeLayer = CAShapeLayer()
shapeLayer.fillColor = (UIColor(red: 57, green: 65, blue: 101, alpha: 1) as! CGColor)
shapeLayer.strokeColor = (UIColor(red: 57, green: 65, blue: 101, alpha: 1) as! CGColor)
If I write my RGB color as:
UIColor(red: 57, green: 65, blue: 101, alpha: 1)
Xcode gives me a warning to change it to:
(UIColor(red: 57, green: 65, blue: 101, alpha: 1) as! CGColor)
When I run Xcode's suggested fix, my app crashes. Why?
Fixing Your Code
You want something like this:
How it Works
A Warning About Inheritance
Xcode warning you about something for that assignment is correct, because you're assigning a
UIColor
to aCGColor
property, but the "fix-me" suggestion is wrong. (Xcode might be doing this because it sees that the class names are similar, but not identical. It might be worth filing a radar.)One place you'll see this a lot is typecasting a custom
UITableViewCell
subclass to the basic cell class, but that won't work here.CGColor
does not inherit fromUIColor
, nor doesUIColor
inherit fromCGColor
. CGColor is aCFTypeRef
and UIColor inherits from `NSObject.One of These Is Not Like the Other
Now, why are these colors different?
CG
stands for "Core Graphics" and is at a lower level than UIKit which defines theUIColor
class. One color object is part of UIKit and the part of Core Graphics.The documentation says that
UIColor
is:A little further down, the overview says that UIColor represents itself internally as a
CGColor
within the predetermined color space.CGColor
, on the other hand, is:Conceptually, very similar, but not exactly the same thing. UIColor is defined in the sRGBA space (as noted here) but
CGColor
will contain info about what color space it's in.Now, the animation layer you're using is part of Core Animation, which is yet another Apple framework. Core Animation isn't part of UIKit, and it's not "on top of" UIKit either, so its classes don't use
UIColor
. Core Animation usesCGColor
for its representations of colors.UIColor
is so easy to instantiate, though, and we're in UIKit-land much of the time anyway. How can we customizeCALayer
and friends while working in ourUIView
s andUIViewController
s? Luckily,UIColor
exposes theCGColor
version of itself, with the.cgColor
property.A Note About Color Spaces
Some of the other answers note that you need to pass values between 0.0 and 1.0. This is true, but it's relevant to note that as of iOS 10, Apple has added some wider-color capabilities to iOS.
This means that it's actually possible to pass in values less than 0.0 and greater than 1.0. From the UIColor documentation:
You probably won't need to worry about color spaces right now, but it's important to understand the fundamentals if you want to do things beyond showing a color onscreen. (Generating inverted or complementary colors are some examples.)
Session 712 from WWDC 2016 (link) covers this new API in depth, and I'd recommend that you take a look at it once you're more comfortable with the basics.
Finally, there's an Apple Tech Note (TN2313) that discusses this in more depth than I could ever imagine. If you want to learn a lot about colors and color spaces on iOS and macOS, read the tech note, entitled "Best Practices for Color Management in OS X and iOS."
You are type casting
UIColor
asCGColor
that is wrong. And RGB values must be the range from 0.0 to 1.0, Check the below code.First of all the parameters
red
,green
,blue
andalpha
must be in range from 0.0 to 1.0Secondly, you must pass the
cgColor
toCGLayer
, e.g.