Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

CMT

macrumors regular
Original poster
Aug 24, 2009
104
10
Hello,

I've been trying to get the Hex value of an NSColor. I found an Apple technical Q&A for this, but can't make it work. I receive a EXC_BAD_ACCESS when calling the method.

The code from the class:

Code:
@interface NSColor (NSColorHexadecimalValue)

-(NSString *)hexadecimalValueOfAnNSColor;

@end

@implementation NSColor (NSColorHexadecimalValue)

-(NSString *)hexadecimalValueOfAnNSColor {
	
	float redFloatValue, greenFloatValue, blueFloatValue;
	int redIntValue, greenIntValue, blueIntValue;
	NSString *redHexValue, *greenHexValue, *blueHexValue;
	
	//Convert the NSColor to the RGB color space before we can access its components
	NSColor *convertedColor=[self colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
	
	if(convertedColor)
	{
		// Get the red, green, and blue components of the color
		[convertedColor getRed:&redFloatValue green:&greenFloatValue blue:&blueFloatValue alpha:NULL];
		
		// Convert the components to numbers (unsigned decimal integer) between 0 and 255
		redIntValue=redFloatValue*255.99999f;
		greenIntValue=greenFloatValue*255.99999f;
		blueIntValue=blueFloatValue*255.99999f;
		
		// Convert the numbers to hex strings
		redHexValue=[NSString stringWithFormat:@"%02x", redIntValue];
		greenHexValue=[NSString stringWithFormat:@"%02x", greenIntValue];
		blueHexValue=[NSString stringWithFormat:@"%02x", blueIntValue];
		
		// Concatenate the red, green, and blue components' hex strings together with a "#"
		return [NSString stringWithFormat:@"#%@%@%@", redHexValue, greenHexValue, blueHexValue];
	}
	return nil;
}
@end

And then the main:

Code:
#import <Cocoa/Cocoa.h>
#import "HexConvert.h"

int main(int argc, char *argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	
	NSColor *blue = [NSColor colorWithCalibratedRed:0.0 green:0.0 blue:1.0 alpha:1.0];
	
	NSString *hexName = [blue hexadecimalValueOfAnNSColor];
	
	NSLog(hexName);
	
	[pool release];
	return NSApplicationMain(argc,  (const char **) argv);
}

Does someone knows what's going on?

Thank you a lot!
 
When you run it in the debugger on exactly which line does it crash. If you have not run it through the debugger you should do this first of all.
 
Crashes on

NSString *hexName = [blue hexadecimalValueOfAnNSColor];

[Switching to process 529]
Running…
Program received signal: “EXC_BAD_ACCESS”.
sharedlibrary apply-load-rules all
warning: Unable to restore previously selected frame.
warning: Unable to restore previously selected frame.
warning: check_safe_call: could not restore current frame

warning: Unable to restore previously selected frame.
warning: Unable to restore previously selected frame.
warning: Unable to restore previously selected frame.
warning: check_safe_call: could not restore current frame

warning: Unable to restore previously selected frame.
warning: Unable to restore previously selected frame.
warning: Unable to restore previously selected frame.
kill
warning: Unable to restore previously selected frame.
Current language: auto; currently objective-c
quit
 
Yes, a imported (#import "HexConvert.h")

Pretty strange bug. The complete debbuger:


[Session started at 2010-03-30 12:51:37 -0300.]
GNU gdb 6.3.50-20050815 (Apple version gdb-1346) (Fri Sep 18 20:40:51 UTC 2009)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin".tty /dev/ttys001
Loading program into debugger…
Program loaded.
run
[Switching to process 891]
Running…
Program received signal: “EXC_BAD_ACCESS”.
sharedlibrary apply-load-rules all
warning: Unable to restore previously selected frame.
warning: Unable to restore previously selected frame.
warning: check_safe_call: could not restore current frame

warning: Unable to restore previously selected frame.
warning: Unable to restore previously selected frame.
warning: Unable to restore previously selected frame.
warning: check_safe_call: could not restore current frame

warning: Unable to restore previously selected frame.
warning: Unable to restore previously selected frame.
warning: Unable to restore previously selected frame.
kill
warning: Unable to restore previously selected frame.
Current language: auto; currently objective-c
quit

The Debugger has exited with status 0.(gdb)
 
Can you post details of exactly what is in which file? Are both the @interface and @implementation of the category in the .h file? If so that's wrong: move the @implementation to a .m file.
 
No they are separated in HexUtility.h and .m . In .h the @interface and @implementation in .m .

This is driving me crazy
 
Can you test if blue is nil after creating? I'm wondering if there is an issue with using NSColor/AppKit classes in a command line app. Especially as you have not created an instance of NSApplication which, I think, initialises AppKit in some way.

I note that AppKit, in general, is not daemon-safe and required a connection to the GUI.

See the overview of NSApplication for details of how you should be creating an NSApplication object...
 
Hmm ok I'll search about it.

By the way, here is an Xcode project with files.
 

Attachments

  • HexUtility.zip
    27.4 KB · Views: 68
I added:

Code:
if (blue == nil) {
	NSLog(@"Yes it is nil");
}
else {
	NSLog(@"No it is not nil");
}

and debugger returned 'No it is not nil' :)
 
Take note of what your warnings tell you when you compile. You should get a warning about incompatible pointer types. What does the getRed:green:blue:alpha: method expect?

This should be a one word modification.
 
Ouch!

from the documentation:

Declaration: - (void)getRed:(CGFloat *)red green:(CGFloat *)green blue:(CGFloat *)blue alpha:(CGFloat *)alpha
 
The forum messed up a little.

Code:
- (void)getRed:(CGFloat *)red green:(CGFloat *)green blue:(CGFloat *)blue alpha:(CGFloat *)alpha

Ok, I changed from variables:

Code:
float redFloatValue, greenFloatValue, blueFloatValue;

To:

Code:
CGFloat *redFloatValue, greenFloatValue, blueFloatValue;

And now I get an error on
Code:
redIntValue=redFloatValue*255.99999f;
.

"Invalid operands to binary *"
 
It's probably a case that the example code you used was out of date. What you put would have been fine a few years ago. For almost all cases you shouldn't be using basic C type declarations (int, float, unsigned), but the 64 bit safe versions (NSInteger, CGFloat, NSUInteger) which make sure the code works fine in 32 and 64 bit environments. This includes your declaration of int.
 
:D

Works now, perfectly. It would be helpful if Apple corrects that.

Help them to help you (and others).

There is a small feedback box at the bottom of the QA1576 webpage:
Did this document help you? Yes It's good, but... Not helpful...
Click the link "It's good but..." and tell them exactly what problem you had.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.