kso*_*sol 7 core-graphics objective-c ios automatic-ref-counting
我有一个编译没有问题的代码.它在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);
}
Run Code Online (Sandbox Code Playgroud)
Xcode突出显示第12行(nil];作为错误行的第12 行).
对于Peter Hosey,这是调试器输出:
(gdb) po startColor
<CGColor 0x1deca0> [<CGColorSpace 0x1d3280> (kCGColorSpaceDeviceGray)] ( 1 1 )
Current language: auto; currently objective-c
(gdb) po endColor
<CGColorSpace 0x1bf120> (kCGColorSpaceDeviceRGB)
(gbd)
Run Code Online (Sandbox Code Playgroud)
我的模拟器(和iPhone)在iOS 5上运行.
什么可能导致这次崩溃?
Bra*_*son 14
解决此问题的一种方法是将UIColors传递给函数,而不是CGColorRefs,并(id)[color1 CGColor]为colors数组的每个元素使用强制转换.这似乎是人们现在最常用的解决这个问题的方式.
我在这个答案中指出了一个用法,并在这个Apple开发者论坛帖子中对此进行了扩展讨论.如果你-CGColor在声明NSArray时使用UIColor的方法,并转换为id,那么一切都会自动为你桥接.正如gparker在上面链接的论坛帖子中所述:
文档描述的自动情况仅适用于调用返回CF类型的Objective-C方法,然后立即将结果转换为Objective-C对象类型.如果您对方法结果执行任何其他操作,例如将其分配给CF类型的变量,则它不再是自动的.
正如hatfinch指出的那样,这可能意味着放置在临时变量中的CGColorRefs在您最后一次引用UIColors之后不会挂起,除非您明确地保留它们.像那个论坛帖子中的其他人一样,我错误地认为这是桥接实现中的一个错误,但我可以看到我读错了.
hat*_*nch 12
你没有让whiteColor和lightGrayColor保持活着.您从UIColors获得永远不会保留的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);
Run Code Online (Sandbox Code Playgroud)
您可以请求Apple声明 - [UIColor CGColor] objc_returns_inner_pointer,这会使您的代码更简单,但该属性实际上是为不可保留的指针保留的.
| 归档时间: |
|
| 查看次数: |
3100 次 |
| 最近记录: |