问题
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?
回答1:
First of all the parameters red
,green
, blue
and alpha
must be in range from 0.0 to 1.0
Secondly, you must pass the cgColor
to CGLayer
, e.g.
let color = UIColor(red: 57.0/255.0, green: 65.0/255.0, blue: 101.0/255.0, alpha: 1)
shapeLayer.fillColor = color.cgColor
shapeLayer.strokeColor = color.cgColor
回答2:
You are type casting UIColor
as CGColor
that is wrong. And RGB values must be the range from 0.0 to 1.0, Check the below code.
let circlePath = UIBezierPath(arcCenter: CGPoint(x: bounds.origin.x+60,y: bounds.origin.y+107), radius: CGFloat(6), startAngle: CGFloat(0), endAngle:CGFloat(7), clockwise: true)
let shapeLayer = CAShapeLayer()
shapeLayer.path = circlePath.cgPath
circlePath.lineCapStyle = .round
let color = UIColor(red: 57.0/255.0, green: 65.0/255.0, blue: 101.0/255.0, alpha: 1).cgColor
shapeLayer.fillColor = color
shapeLayer.strokeColor = color
shapeLayer.lineWidth = 3.0
self.layer.addSublayer(shapeLayer)
回答3:
Fixing Your Code
You want something like this:
let shapeLayer = CAShapeLayer()
shapeLayer.fillColor = UIColor(red: 57, green: 65, blue: 101, alpha: 1).cgColor
shapeLayer.strokeColor = UIColor(red: 57, green: 65, blue: 101, alpha: 1).cgColor
How it Works
A Warning About Inheritance
Xcode warning you about something for that assignment is correct, because you're assigning a UIColor to a CGColor 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 from UIColor
, nor does UIColor
inherit from CGColor
. CGColor is a CFTypeRef
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 the UIColor
class. One color object is part of UIKit and the part of Core Graphics.
The documentation says that UIColor
is:
An object that stores color data and sometimes opacity (alpha value)."
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:
A set of components that define a color, with a color space specifying how to interpret them."
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 uses CGColor
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 customize CALayer
and friends while working in our UIView
s and UIViewController
s? Luckily, UIColor
exposes the CGColor
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:
When working in an extended color space, color values are not clamped to fit inside the color gamut, meaning that component values may be less than 0.0 or greater than 1.0. When displayed on an sRGB display, such colors are outside the gamut and will not be rendered accurately.
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."
来源:https://stackoverflow.com/questions/44887845/using-uicolor-with-cashapelayer