Best way to manage memory with NSColor and CGColor

740 views Asked by At

I had to develop an app compatible from OSX 10.6 to the latest, which requires managing the memory manually. In this app, I want to have all my colors in one place and access it through appDelegate's properties.

My first approach was to use NSColor object :

@property (strong, nonatomic) NSColor *myBlue;

@synthesize myBlue = _myBlue;   

_myBlue = [[NSColor colorWithCalibratedRed:20.0/255.0 green:20.0/255.0 blue:0.0/255.0 alpha:1.0/1.0] retain];

And I release it in the dealloc method of appDelegate :

[_myBlue release];

When I needed an NSColor in another class, I access it doing :

appDelegate.myBlue

And if I needed a CGColor, I used this function :

- (CGColorRef)NSColorToCGColor:(NSColor *)color
{
    NSInteger numberOfComponents = [color numberOfComponents];
    CGFloat components[numberOfComponents];
    CGColorSpaceRef colorSpace = [[color colorSpace] CGColorSpace];
    [color getComponents:(CGFloat *)&components];
    CGColorRef cgColor = CGColorCreate(colorSpace, components);

    return cgColor;
}

view.layer.backgroundColor = [[GlobalFunctions sharedGlobalFunctions]  NSColorToCGColor:appDelegate.myBlue]];

But this function is known to cause a memory leak because the object cgColor is never released. Nota : I need to use this function because with the OSX 10.6 SDK, I can't use myBlue.CGColor to generate a CGColor from a NSColor.

My second approach is to use CGColor like this :

@property (nonatomic) struct CGColor *myRed;

@synthesize myRed = _myRed;

_myRed = CGColorCreateGenericRGB(20.0/255.0, 20.0/255.0, 255.0/255.0, 1.0/1.0);

And I release it in the dealloc method of appDelegate :

CGColorRelease(_myRed);

When I need an CGColor in another class, I access it doing :

appDelegate.myRed

And if I need a NSColor, I use this function :

textView.textColor = [NSColor colorWithCIColor: [CIColor colorWithCGColor: appDelegate.myRed]];

Finally, the question is : What is the best practice to manage NSColor and CGColor, in order to avoid memory leak and to do it elegantly ?

1

There are 1 answers

0
pco494 On

For NSColor if I only have a limited palette of standard colours that the app uses I typically make a category fro NSColor and extend the already existing pattern of [NSColor blackColor]etc. with my own colors like below.

These are static singletons that will never be deallocated for the app lifetime. Instead they are shared. As they are immutable there is no risk in sharing them. This is not a memory leak, just a static memory overhead.

In principle a similar approach should be possible for CGColor, the issue is that there is no class to extend then I think, so just make a new source file with appropriate functions returning the CGColor structs.

NSColor+CustomColors.h

#import <Cocoa/Cocoa.h>

@interface NSColor (CustomColors)

+(NSColor *)pinkColor;
+(NSColor *)darkGreenColor;

@end

NSColor+CustomColors.m

#import "NSColor+CustomColors.h"

@implementation NSColor (CustomColors)

+(NSColor *)pinkColor{

    static NSColor *pinkColor;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        pinkColor = [NSColor colorWithSRGBRed:247.0 / 255.0 green:234.0 / 255.0 blue:228.0 /255.0  alpha:1.0];
});
    return pinkColor;
    }

+(NSColor *)darkGreenColor{

    static NSColor *darkGreenColor;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
         darkGreenColor = [NSColor colorWithSRGBRed:0.0 green:132.0 / 255.0 blue:0.0  alpha:1.0];
});
    return darkGreenColor;
}

@end