CGColorGetComponents() not returning the correct values for black and for white
What you're not grasping is that nothing about CGColorGetComponents makes any claims or guarantees about how many components there are or what they mean. That information is contained in the color's color space. If you look at the color space of white and black, you will see they are both forms of grey:
let sp = CGColorGetColorSpace(UIColor.whiteColor().CGColor)
println(sp) // kCGColorSpaceDeviceGrey
Thus, they are expressed in just two values: the amount of grey, and the alpha.
Hence, white is [1.0,1.0]
- which, if you ignore the extra two numbers which you should not have been reading in the first place, is exactly what you got.
Similarly, black is [0.0,1.0]
, which is also what you got.
What does CGColorGetComponents() return?
Yes, it returns an array of CGFloats
. Specifically, it returns "an array of intensity values for the color components (including alpha) associated with the specified color."
The color components returned depend on what color space the passed CGColorRef
uses.
More information can be found in the CGColor documentation.
Different behaviours for different colors in drawRect:
Similar to this answer I am guessing that darkGrayColor
and lightGrayColor
both represent gray-sacle values rather tan rgba-values. And therefore dont have 4 comoponents but only 2.
You might want / have to use a different approach of setting the color:
CGContextSetStrokeColorWithColor(context, [UIColor darkGrayColor].CGColor);
Is there an issue with CGColorGetComponents?
[UIColor whiteColor]
and [UIColor blackColor]
use [UIColor colorWithWhite:alpha:]
to create the UIColor. Which means this CGColorRef has only 2 color components, not 4 like colors created with [UIColor colorWithRed:green:blue:alpha:]
.
Of course you can NSLog those too.
if (CGColorGetNumberOfComponents(myColorRef) == 2) {
const CGFloat *colorComponents = CGColorGetComponents(myColorRef);
NSLog(@"r=%f, g=%f, b=%f, a=%f", colorComponents[0], colorComponents[0], colorComponents[0], colorComponents[1]);
}
else if (CGColorGetNumberOfComponents(myColorRef) == 4) {
const CGFloat * colorComponents = CGColorGetComponents(myColorRef);
NSLog(@"r=%f, g=%f, b=%f, a=%f", colorComponents[0], colorComponents[1], colorComponents[2], colorComponents[3]);
}
else {
NSLog(@"What is this?");
}
Be aware that there are different colorSpaces too. So if you need this code for more than logging (e.g. saving RGBA strings to json) you have to check (and probably convert) the colorSpace too.
How to get color components of a CGColor correctly
Most likely wrong colorspace. I guess the alpha component of the grayscale colorspace gets where you think the green component should be.
I use this function to create a string from UIColor, I only encounter RGB and Grayscale colorspaces, so I just interpret every color with less than 4 (R+G+B+A) components as grayscale.
if (CGColorGetNumberOfComponents(color.CGColor) < 4) {
const CGFloat *components = CGColorGetComponents(color.CGColor);
color = [UIColor colorWithRed:components[0] green:components[0] blue:components[0] alpha:components[1]];
}
if (CGColorSpaceGetModel(CGColorGetColorSpace(color.CGColor)) != kCGColorSpaceModelRGB) {
NSLog(@"no rgb colorspace");
// do seomthing
}
const CGFloat *components = CGColorGetComponents(color.CGColor);
NSString *colorAsString = [NSString stringWithFormat:@"%f,%f,%f,%f", components[0], components[1], components[2], components[3]];
of course this method is not save for all cases, you should adopt it to your requirements.
Strange Behavior Of UIColor As Function Parameter In Swift
You could try something like this:
var colors: [UIColor] = []
func setColors(colors: UIColor...) {
self.colors = colors
}
override func drawRect(rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
let colorSpace: CGColorSpaceRef = CGColorSpaceCreateDeviceRGB()
var gradientColors: [CGColor] = []
var colorLocations: [CGFloat] = []
var i: CGFloat = 0.0;
for color in colors {
gradientColors.append(color.CGColor)
colorLocations.append(i)
i += CGFloat(1.0) / CGFloat(colors.count)
}
let gradient: CGGradientRef = CGGradientCreateWithColors(colorSpace, gradientColors, colorLocations)
CGContextDrawLinearGradient(context, gradient, CGPoint(x: 0.0, y: self.frame.size.height / 2), CGPoint(x: self.frame.size.width, y: self.frame.size.height / 2), 0)
}
Side Note: You don't want to capitalize variable names. So I changed self.Colors
to self.colors
What is the correct way to update RGB values of a colorLiteral in Xcodet?
Double click on the little square, this will pop up:
press "Other". The usual macOS color picker shows up. You can then go to the second tab, and select the RGB sliders option. There is also an option to enter floating point values if you click on the gear icon:
Is there a conventional method for inverting NSColor values?
Simple: The components are all 0–1, so subtract each component from 1 to get the complement's value.
Examples:
- Red = 1, 0, 0; complement = 0, 1, 1 = cyan
- Yellow = 1, 1, 0; complement = 0, 0, 1 = blue
- White = 1, 1, 1; complement = 0, 0, 0 = black
- Deep orange = 1, 0.25, 0; complement = 0, 0.75, 1 = sky blue
As you can guess, this is a symmetric operation. Inverting the inverse will get you exactly the color you started with.
Is it possible to map @Published to @Binding?
It is possible with computable Binding, like
PaintColor(color: color, isSelected: Binding(
get: { state.selectedColor == color },
set: { state.selectedColor = $0 ? color : .white }
))
.frame(maxWidth: .infinity)
*actually if it is possible all unselected then it is needed to make selectedColor optional (and then reset to nil
instead of .white
above)
@Published var selectedColor: Color? = .white
Related Topics
The 'Pods' Target Has Transitive Dependencies That Include Static Binaries' When Installing Gcm
Usage of String.Range in Swift 3.0
Cannot Create PDF Document with 400+ Pages on iOS
How to Show "Would Like to Send You Push Notifications" Alert View Again
Hit Detection When Drawing Lines in iOS
How to Only Override a Method Depending on the Runtime System iOS Version
Thread 1:Exc_Bad_Access (Code = 1, Address = 0X30000008)
How to Properly Remove Node When Out of Screen Bounds
Get Responseobject on Failure Block Afnetworking 3.0
Following in App Purchase, App Crashing on Startup. Productidentifier=Nil
Detect If iOS App Is Downloaded from Apple's Testflight
Conditionally Hide Code from the Compiler
Calling Instance Method During Initialization in Swift
How to Unwind Through Multiple Views Without Displaying Intermediate Views