Problema con CFArrayRef y NSArray al dibujar gradiente usando ARC

Tengo un proyecto ARC y estoy tratando de dibujar un gradiente lineal vertical. El código a continuación funciona en el simulador, pero arroja un error de memory / EXC_BAD_ACCESS cuando se testing en el dispositivo. La aplicación se cuelga con las siguientes dos líneas de código:

 NSArray *colorArray = [NSArray arrayWithObjects:(__bridge id)topColor, (__bridge id)bottomColor, nil]; CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef) colorArray, colorLocations); 

Estas dos líneas de código se toman del siguiente código (provisto como reference):

 - (void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); [self createGradientForContext:context andView:self.captionView]; [self createGradientForContext:context andView:self.linksView]; [self createGradientForContext:context andView:self.commentView]; } - (void)createGradientForContext:(CGContextRef)context andView:(UIView *)view { CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGFloat colorLocations[] = { 0.0f, 1.0f }; CGColorRef topColor = [[UIColor colorWithRed:51.0f/255.0f green:51.0f/255.0f blue:51.0f/255.0f alpha:1.0f] CGColor]; CGColorRef bottomColor = [[UIColor colorWithRed:48.0f/255.0f green:48.0f/255.0f blue:48.0f/255.0f alpha:1.0f] CGColor]; NSArray *colorArray = [NSArray arrayWithObjects:(__bridge id)topColor, (__bridge id)bottomColor, nil]; CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge_retained CFArrayRef) colorArray, colorLocations); CGRect frame = view.frame; CGPoint startPoint = CGPointMake(CGRectGetMidX(frame), CGRectGetMinY(frame)); CGPoint endPoint = CGPointMake(CGRectGetMidX(frame), CGRectGetMaxY(frame)); CGContextSaveGState(context); CGContextAddRect(context, frame); CGContextClip(context); CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0); CGContextRestoreGState(context); CGGradientRelease(gradient); CGColorSpaceRelease(colorSpace); } 

Gracias de antemano por cualquier orientación.

Intente simplemente usar un CFArrayRef y evite el puenteo y vea si hace una diferencia.

 CGFloat topColorComps[] = {51.0f/255.0f, 51.0f/255.0f, 51.0f/255.0f, 1.0f}; CGFloat bottomColorComps[] = {48.0f/255.0f, 48.0f/255.0f, 48.0f/255.0f, 1.0f}; CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB(); CGColorRef topColor = CGColorCreate(rgb, topColorComps); CGColorRef bottomColor = CGColorCreate(rgb, bottomColorComps); CGColorSpaceRelease(rgb); CFMutableArrayRef colorArray = CFArrayCreateMutable(NULL, 2, &kCFTypeArrayCallbacks); CFArrayAppendValue(colorArray, topColor); CFArrayAppendValue(colorArray, bottomColor); CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, colorArray, colorLocations); CFRelease(colorArray); CFRelease(topColor); CFRelease(bottomColor); 

Ahora para explicar por qué estabas chocando …

El problema son estas dos líneas:

 CGColorRef topColor = [[UIColor colorWithRed:51.0f/255.0f green:51.0f/255.0f blue:51.0f/255.0f alpha:1.0f] CGColor]; CGColorRef bottomColor = [[UIColor colorWithRed:48.0f/255.0f green:48.0f/255.0f blue:48.0f/255.0f alpha:1.0f] CGColor]; 

Este es un problema muy común; hay muchas preguntas sobre Stack Overflow por parte de usuarios que han sido mordidos por esto.

El problema es que, debido a que esos objects UIColor nunca son referencedos después de esas líneas, ARC los libera inmediatamente, y debido a que esos objects UIColor son los únicos propietarios de los objects CGColor, los UIColors lanzan los CGColors de inmediato, dejándote con dos objects CGColor muertos. Lo que luego intenta poner en una matriz.

Como descubrió, cambiar de NSArray a CFArray puro no solucionará esto. Cambiar de UIColor a CGColor puro es una solución; el otro es poner tu propia propiedad en CGColors:

 CGColorRef topColor = CGColorRetain([[UIColor colorWithRed:51.0f/255.0f green:51.0f/255.0f blue:51.0f/255.0f alpha:1.0f] CGColor]); CGColorRef bottomColor = CGColorRetain([[UIColor colorWithRed:48.0f/255.0f green:48.0f/255.0f blue:48.0f/255.0f alpha:1.0f] CGColor]); ⋮ CGColorRelease(topColor); CGColorRelease(bottomColor); 
    Intereting Posts