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

618 views Asked by At

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;
}
2

There are 2 answers

1
ughoavgfhw On BEST ANSWER

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.

0
dreamlax On

This is your problem, I think:

NSColor *color1 = [NSUnarchiver unarchiveObjectWithData:data];
_color = color1;

You don't own the object returned by unarchiveObjectWithData: but you assign it to an instance variable and treat it as if it is owned by you. You can explicitly take ownership of the object just as you do in your setter, by using the copy method:

_color = [color1 copy];