About CGColor/definition

372 views Asked by At

In a class I have a variable myColor of type CGColorRef declared as follow:

@implementation MyClass
{
    .......
    CGColorRef myColor;
    .......

Here are two lines of Objective C code:

First line:

myColor=[UIColor orangeColor].CGColor;

Second line:

myColor=[UIColor colorWithRed:1.000 green:0.500 blue:0.000 alpha:1.000].CGColor;

I first expected them to be equivalent, but they are not.

I know they are not equivalent, because when I use the first one my program works. And when I use the second one it crashes later down the road. Showing more code here would be totally irrelevant to the question.

Can someone explain the difference? That will hopefully allow me to modify my code and be able to use the second line.

Just for reference, it crashes in (with: Thread 1: EXC_BAD_ACCESS (code=1, address=0x881b370e0)):

- (void)drawRect:(CGRect)rect
{
    .......
    CGContextSetStrokeColorWithColor(context,myColor); // Crash here !!!
    CGContextStrokeEllipseInRect(context, rectangle);
    .......
}
2

There are 2 answers

4
Prashant Tukadiya On BEST ANSWER

Crash is because may be you don't have strong ref (property) of myColor object. You might has assign property

Reason why [UIColor orangeColor] works but not [UIColor colorWithRed...

When you use [UIColor orangeColor], you don't create the object; you get a reference to it and something else manages its life cycle.

When you init a new UIColor object, you're responsible for making sure it is still valid when used. "assign" doesn't increase the object's reference count; "strong" does.

Hope it is helpful

EDIT

Decleare the one property like this

@property (nonatomic,strong) UIColor * myUIColor;

Now When you can

do this like

myUIColor =[UIColor colorWithRed:1.000 green:0.500 blue:0.000 alpha:1.000]

when you need CGColor

myUIColor. CGColor

6
Ben Zotto On

You're assigning to an instance variable of Core Foundation type CGColorRef. That type is not an ObjC object type, so is not subject to ARC (automatic memory management), which means you need to manage its memory manually.

Both of your examples are actually incorrect, but the reason you don't see the crash initially when you assign [UIColor orangeColor].CGColor is because of a lucky coincidence: the orange color object is probably a long-lived singleton object, and its internal CGColor reference is thus also long-lived, so your assignment to ivar works and later access happens to work-- but this is just a red (orange?) herring.

You do see a crash in the other case because the UIColor object that you create in passing ends up being immediately deallocated because it's not used again. Thus the CGColorRef value that you pull from it and assign to your ivar is is also immediately invalid and radioactive when you try to use it later.

To store a CGColorRef safely in your object, you need to have ownership of it, which in your case means explicitly retaining the CGColorRef you get from UIColor:

myColor = CGColorRetain([UIColor colorWithRed:1.000 green:0.500 blue:0.000 alpha:1.000].CGColor);

Or even better would be to bypass UIColor altogether, and just use the function that directly gives you a color ref with create ownership semantics:

myColor = CGColorCreateGenericRGB(1.0, 0.5, 0.0, 1.0);

In either case, you now "own" this reference, which means it's safe to use later, and also means you're responsible for cleaning it up when you're done, e.g.:

- (void)dealloc 
{
    CGColorRelease(myColor);
}

See also this Apple Tech Q&A doc that goes into almost this same example.


The form of memory management required with Core Foundation objects (CGColorRef is one of them) is very similar to the older, pre-ARC ObjC manual system, where you increment a retain count at the point where you wish to hold ("own") the reference, and then decrement (release) when you no longer need it to be valid. Apple has good docs for how to best think about this. In this case, assigning the reference to your instance variable means you want to keep it around as valid for some amount of time. Generally you retain at the point of assignment (either explicitly or by getting the reference via a Create function), and then you'd release it when the object is deallocated.