CG Gradient在模拟器上运行,但不在iPhone上运行

我有一个编译没有问题的代码。 它在iPhone模拟器上运行良好,但在我的设备上,我得到了一个EXC_BAD_ACCESS。

这发生在一个帮助函数绘制渐变。 我遵循这个教程来做到这一点。 我有的代码如下:

- (void) drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); CGColorRef whiteColor = [UIColor whiteColor].CGColor; CGColorRef lightGrayColor = [UIColor colorWithRed:230.0/255.0 green:230.0/255.0 blue:230.0/255.0 alpha:1.0].CGColor; CGColorRef separatorColor = [UIColor colorWithRed:208.0/255.0 green:208.0/255.0 blue:208.0/255.0 alpha:1.0].CGColor; CGRect paperRect = self.bounds; CGRect nameRect = self.nameLabel.frame; CGPoint sepStartPoint = CGPointMake(nameRect.origin.x, nameRect.origin.x + nameRect.size.height + 2); CGPoint sepEndPoint = CGPointMake(nameRect.origin.x + nameRect.size.width, nameRect.origin.x + nameRect.size.height + 2); drawLinearGradient(context, paperRect, lightGrayColor, whiteColor); draw1PxStroke(context, sepStartPoint, sepEndPoint, separatorColor); } // Callee, where the problem is void drawLinearGradient(CGContextRef context, CGRect rect, CGColorRef startColor, CGColorRef endColor) { CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGFloat locations[] = { 0.0, 1.0 }; NSArray *colors = [NSArray arrayWithObjects: (__bridge id)startColor, (__bridge id)endColor, nil]; // Here is the line CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef) colors, locations); CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect)); CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect)); CGContextSaveGState(context); CGContextAddRect(context, rect); CGContextClip(context); CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0); CGContextRestoreGState(context); CGGradientRelease(gradient); CGColorSpaceRelease(colorSpace); } 

Xcode突出显示第12行(带有nil];作为错误行。

对于Peter Hosey,这里是debugging器的输出:

 (gdb) po startColor <CGColor 0x1deca0> [<CGColorSpace 0x1d3280> (kCGColorSpaceDeviceGray)] ( 1 1 ) Current language: auto; currently objective-c (gdb) po endColor <CGColorSpace 0x1bf120> (kCGColorSpaceDeviceRGB) (gbd) 

我的模拟器(和iPhone)在iOS 5上运行。

什么可能导致这次崩溃?

解决这个问题的一种方法是将UIColors传递到您的函数中,而不是CGColorRefs中,并且对colors数组的每个元素使用(id)[color1 CGColor] 。 这似乎是目前人们正在解决这个问题的最普遍的方式。

我在这个答案中指出了一个这样的用法,在这个苹果开发者论坛主题中有关于这个问题的扩展讨论。 如果你在声明你的NSArray的时候使用了一个UIColor的-CGColor方法,并且转换为id,那么所有的东西都会自动为你自动桥接。 作为gparker在上述链接论坛线程状态:

本文档中描述的自动情况仅适用于调用返回CFtypes的Objective-C方法,然后立即将结果转换为Objective-C对象types。 如果你对方法的结果做了其他的事情,比如把它赋给一个CFtypes的variables,那么它就不再是自动的了。

正如hatfinch指出的那样,这可能意味着放置在临时variables中的CGColorRefs在上次引用UIColors之后不会挂起,除非明确地保留它们。 就像论坛主题中的其他人一样,我错误地认为这是桥接实现中的一个错误,但是我可以看到我正在读这个错误。

你没有保持你的whiteColor和lightGrayColor活着。 您从UIColors获得的CGColorRefs不属于永不保留的CGColorRefs。 你的代码应该是:

 CGColorRef whiteColor = CFRetain([UIColor whiteColor].CGColor); CGColorRef lightGrayColor = CFRetain([UIColor colorWithRed:230.0/255.0 green:230.0/255.0 blue:230.0/255.0 alpha:1.0].CGColor); CGColorRef separatorColor = CFRetain([UIColor colorWithRed:208.0/255.0 green:208.0/255.0 blue:208.0/255.0 alpha:1.0].CGColor); // ... drawLinearGradient(context, paperRect, lightGrayColor, whiteColor); draw1PxStroke(context, sepStartPoint, sepEndPoint, separatorColor); CFRelease(whiteColor); CFRelease(lightGrayColor); CFRelease(separatorColor); 

你可以请求苹果声明 – [UIColor CGColor]作为objc_returns_inner_pointer ,这将使你的代码更简单,但是这个属性真的是保留给不可保留的指针。