Search code examples
objective-cmethodsuicolorcgcolor

Issue assigning custom UIColor to class property


I'm having troubles passing through a custom UIColor to a method I've created.

Basically, I have a class that extends the UIButton class, in which I can assign whatever colours I want to different, commonly modified, properties of the class. To do this I often have to set the colours of things to "uiColorParameter.CGColor", or "uiColorParameter". My issue is that when I pass a custom colour as an argument (So instead of [UIColor whiteColor] (for example) I do [UIColor colorWithRed:...], the app crashes with the error "Thread 1: EXC_BAD_ACCESS (code=1, address=0x20)".

2 times the class is utilised in a view controller.

[_beginButton updateButtonBorderWithCornerRadius:10 borderWidth:2.75 borderColor:[RoundedButton appRedColor]];
[_beginButton setEventEffectsWithColor:[UIColor redColor] secondColor:[RoundedButton appRedColor]];

In the custom classes H

@property (assign) UIColor *pColor;
@property (assign) UIColor *sColor;

In the custom class

- (void)updateButtonBorderWithCornerRadius:(CGFloat)bRadius borderWidth:(CGFloat)bWidth borderColor:(UIColor *)bColor
{
    self.layer.cornerRadius = bRadius;
    self.layer.borderWidth = bWidth;
    self.layer.borderColor = bColor.CGColor;
}

- (void)setEventEffectsWithColor:(UIColor *)fColor secondColor:(UIColor *)sColor
{
    [self setPrimaryBorderColor:fColor];
    [self setSecondaryBorderColor:sColor];

    [self addTarget:self action:@selector(highlight) forControlEvents:UIControlEventTouchDown];
    [self addTarget:self action:@selector(unhighlight) forControlEvents:UIControlEventTouchUpInside];
    [self addTarget:self action:@selector(unhighlight) forControlEvents:UIControlEventTouchDragExit];
}

- (void)highlight
{
    self.layer.borderColor = pColor.CGColor;
    self.titleLabel.textColor = pColor;
}

- (void)unhighlight
{
    self.layer.borderColor = sColor.CGColor; //Where the error occurs
    self.titleLabel.textColor = sColor;
}

- (void)setPrimaryBorderColor:(UIColor *)color
{
    pColor = color;
}

- (void)setSecondaryBorderColor:(UIColor *)color
{
    sColor = color;
}

+ (UIColor *)appRedColor
{
    return [UIColor colorWithRed:0.68 green:0.14 blue:0.09 alpha:1];
}

The first method "updateButtonBorder..." works completely fine, no errors. However, for the second method, regardless of how you pass through the custom UIColor (whether has a class variable, as I've done, or as a literal [UIColor colorWithRed:...) it will crash. However, if I send an ordinary [UIColor whiteColor], for example, it will work perfectly fine...


Solution

  • You have a memory management problem due to your pColor and sColor properties being declared as assign instead of strong.

    It appears to work with system colors because those system color instances are probably kept in memory by UIKit. But your custom colors are not.

    Change:

    @property (assign) UIColor *pColor;
    @property (assign) UIColor *sColor;
    

    to:

    @property (nonatomic, strong) UIColor *pColor;
    @property (nonatomic, strong) UIColor *sColor;
    

    You should very rarely, if ever, use assign with object pointers.