Search code examples
cocoacolorsstrokensbezierpath

Cocoa NSBezierPath - stroke. Crashes with color different from predefined one


I have the following problem. I'm writing my own class which must draw a circle of specified size, fill it with gradient.

I made it with a circle being a NSBezierPath, to which I draw my gradient using

[gradient drawInBezierPath:circle relativeCenterPosition:gradPoint]

So everything works great except one thing: when I execute the following command at the end of my drawRect: code:

[borderColor set]; 
[circle stroke];

I get the error: (Program recieved signal: "EXC_BAD_ACCESS") and debugger points to the line with

[borderColor set];

I set borderColor as

[NSColor colorWithCalibratedRed:0.8 green:0.8 blue:0.8 alpha:1.0]

for example.

It only works normally if i set my borderColor as any predefined color: blackColor, clearColor, greenColor. But any one which I try to set manually, crashes.

Does somebody know about any restrictions about colors or something that could cause such problem? I didn't find anything special about stroke color of BezierPath.

Thank you.


Solution

  • The problem is that you are not properly retaining the borderColor instance variable. The -colorWithCalibratedRed:green:blue:alpha: method creates an autoreleased object, which, unless you retain it, will be automatically autoreleased (and deallocated) once the application event loop returns. The next time around, when you try to send a message to the deallocated object, problems occur.

    The reason it happens to be working with -blackColor, -clearColor, etc. is pure luck (sort of). Those "convenience color" methods happen to return singleton instances that will never be deallocated. For example, if someone asks for -blackColor 1000 times, there's no sense in wasting memory by creating 1,000 separate instances; instead, the single (shared) instance is returned. However, this is a private implementation detail that you generally should not rely on.

    How to correct this depends on how borderColor has been defined. If it's defined and implemented as a property, and you're setting it via the -setBorderColor: method, then make sure the property is defined as a retain:

    @property (retain) NSColor *borderColor;
    

    Or, if you're setting the borderColor value by working with the instance variable directly, you should wrap it with a retain:

    // remember to safely release the old value if necessary 
    borderColor = [[NSColor colorWithCalibratedRed:0.8
                            green:0.8 blue:0.8 alpha:1.0] retain];