我正在为iOS 5创建一个应用程序,我正在绘制一些渐变。我在ARC之前总是使用以下渐变代码,但是现在它不再适用于我的设备(但是,它可以在模拟器上工作),当我多次使用它时(所以我认为这是一个内存管理问题)。无论如何,这是代码:
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGFloat locations[] = { 0.0, 1.0 };
NSArray *colors = [NSArray arrayWithObjects:(__bridge id)startColor, (__bridge id)endColor, nil];
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);
最初,没有__bridge语句,我按照Xcode的建议添加了它们。究竟是什么导致了这个问题?
答案 0 :(得分:4)
我遇到了同样的问题。我已经使用CGGradientCreateWithColorComponents
来解决我的问题。您必须将CGColorRef
的NSArray转换为CGFloat
s的数组。
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat components[8] = { 0.909, 0.909, 0.909, 1.0, // Start color
0.698f, 0.698f, 0.698f, 1.0 }; // End color
CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, components,
locations, 2);
答案 1 :(得分:3)
您的问题可能与startColor
等变量的生命周期有关。我猜这些可能是通过UIColor的-CGColor
方法创建的CGColorRefs,位于您列出的代码之上的某个位置。
正如我在this answer中描述的那样,除非你明确地保留了那些CGColorRefs,否则它们可能会在生成它们的UIColor被释放后消失。鉴于您从它们中提取CGColorRef后再也不会再使用UIColors,ARC可能会决定在您有机会使用CGColorRefs之前解除分配这些UIColors。我已经看到模拟器和实际设备之间的对象生命周期不同,所以这可以解释一个而不是另一个的崩溃。
我对此的解决方案是使用立即转换为id,如下所示:
NSArray *colors = [NSArray arrayWithObjects:(id)[color1 CGColor],
(id)[color2 CGColor], nil];
编译器在转移CGColorRefs的所有权方面做了正确的事。
还有可能提前释放您的NSArray,在这种情况下,以下代码可能会确保它挂起的时间足够长:
NSArray *colors = [NSArray arrayWithObjects:(__bridge id)startColor, (__bridge id)endColor, nil];
CFArrayRef colorArray = (__bridge_retained CFArrayRef)colors;
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, colorArray, locations);
CFRelease(colorArray);
这将NSArray与Core Foundation连接起来,留下一个保留计数至少为1的CFArrayRef。然后可以在渐变创建中使用它,渐变将有希望保留对它的引用,并手动释放它完成后。
但是,Bringo建议完全在Core Graphics的C API中工作,这可能是最简单的方法。我只是想我会解释你的问题的潜在根源,以防你将来遇到类似事情。