Search code examples
objective-cnsuserdefaultsnscolor

NSColor and NSUserDefaults cause; Program received signal: “EXC_BAD_ACCESS”


I have 3 methods one which gets a color and saves it as a data object in user defaults, one which draws a rectangle and fills it with the color saved in user defaults and one method which initialises and instance of NSColor with the color saved in user defaults when the app launches.

Below are the 3 methods, however the problem is i get this error when i build and run the app, can anyone understand why i get this error and what's wrong with my code.

Program received signal: “EXC_BAD_ACCESS”.

- (void)setColor:(NSColor *)color
{
    _color = [color copy];

    NSData *data = [NSArchiver archivedDataWithRootObject:_color];
    [[NSUserDefaults standardUserDefaults] setObject:data forKey:@"MyColor"];

    [self setNeedsDisplay:YES];
}


    - (void)drawRect:(NSRect)rect 
{

     NSRect rect1 = NSInsetRect([self bounds], 4.0, 4.0);
     NSBezierPath * path;
     [_color set];
     path = [NSBezierPath bezierPathWithRoundedRect:rect1
                                                   xRadius:6.0
                                                   yRadius:6.0];
     [path fill];
}

- (id)initWithFrame:(NSRect)frame
{
    self = [super initWithFrame:frame];
    if (self == nil)
        return nil;

    _color = [NSColor blackColor];
    NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:@"MyColor"];
    if (data != nil){
    NSColor *color1 = [NSUnarchiver unarchiveObjectWithData:data];
    _color = color1;}

    return self;
}

Solution

  • The problem is in your initWithFrame: method. _color is set with either [NSColor blackColor] or [NSUnarchiver unarchiveObjectWithData:data]. Both of these methods return autoreleased objects. You need to retain them to make sure they still exist when drawRect: is called. The easiest way would be to call [_color retain] after the unarchive, so that the blackColor will still be autoreleased if it gets replaced.

    Also, make sure you release the old _color in setColor:. Right now it leaks a NSColor object every time it is called.