I'm using DCRoundSwitch
for a project where I basically need an UISwitch
where I'm able to edit its label contents.
Because I'm using ARC
I refactored the DCRoundSwitch
code to be ARC
-compatible in xcode.
When compiling and running in the simulator it works without any problems.
However, when running on the device it gives me EXC_BAD_ACCESS
near line 57 of DCRoundSwitchKnobLayer.m
There is a bug report at GitHub but no solution has been found yet.
Here is the code that gives EXC_BAD_ACCESS
:
CGGradientRef CreateGradientRefWithColors(CGColorSpaceRef colorSpace, CGColorRef startColor, CGColorRef endColor)
{
CGFloat colorStops[2] = {0.0, 1.0};
CGColorRef colors[] = {startColor, endColor};
//THIS LINE BREAKS THE PROGRAM
CFArrayRef colorsArray = CFArrayCreate(NULL, (const void**)colors, sizeof(colors) / sizeof(CGColorRef), &kCFTypeArrayCallBacks);
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, colorsArray, colorStops);
CFRelease(colorsArray);
return gradient;
}
Any clues would be appreciated.
EDIT: Here are the local variables from xcode:
I had the same problem and I really wanted to convert the code to ARC. The crash occurs because startColor and endColor are already freed when CreateGradientRefWithColors is called.
Here is my fix:
- (void)drawInContext:(CGContextRef)context
{
UIColor *startColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:1.0];
UIColor *endColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];
NSArray *colors = [NSArray arrayWithObjects:(__bridge id)startColor.CGColor, (__bridge id) endColor.CGColor, nil];
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef) colors, locations);
}
This post helped in finding the solution: http://www.bobmccune.com/2012/02/28/a-funny-thing-happened-on-the-way-to-the-arc/
EDIT
Apologies, the correct fix for this code with ARC is:
CGGradientRef CreateGradientRefWithColors(CGColorSpaceRef colorSpace, CGColorRef startColor, CGColorRef endColor)
{
CGFloat colorStops[2] = {0.0, 1.0};
NSArray *colors = [NSArray arrayWithObjects:(id)startColor, (id)endColor, nil];
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, colorStops);
return gradient;
}
You use a bridge conversion from an NSArray of the colors, rather than going to the extra work of creating the the CFArrayRef. This refactoring is shamelessly stolen from the Discussions on Core Graphics 101. Which is an awesome site of turorials on Objective-C.
The Everything you wanted to know about ARC has a few guides about this. The ARC Q&A also has some good guides on this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With