5

我有一个 ARC 项目,正在尝试绘制垂直线性渐变。下面的代码适用于模拟器,但在设备上测试时会引发内存/EXC_BAD_ACCESS错误。该应用程序在以下两行代码中崩溃:

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

这两行代码取自以下代码(仅供参考):

- (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);

}

提前感谢任何和所有的指导。

4

2 回答 2

8

现在解释一下你为什么会崩溃……</p>

问题是这两行:

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];

这是一个非常普遍的问题;被这个问题困扰的用户对 Stack Overflow 提出了很多问题。

问题在于,因为那些 UIColor 对象在这些行之后永远不会被引用,ARC 会立即释放它们——而且因为这些 UIColor 对象是 CGColor 对象的唯一所有者,所以 UIColors 会立即释放 CGColors,给您留下两个死 CGColor 对象。然后您尝试将其放入数组中。

如您所见,从 NSArray 切换到纯 CFArray 并不能解决此问题。从 UIColor 切换到纯 CGColor 是一种解决方案;另一种是将您自己的所有权放在 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);
于 2012-05-08T05:06:10.920 回答
5

尝试只使用 aCFArrayRef并避免桥接,看看它是否有所作为。

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);
于 2012-05-08T01:28:17.807 回答