为方法创建渐变和返回

对于有关iPhone和Quartz编程的noobish问题,我们深表歉意。 刚刚开始从C ++转换为Objective-C 🙂

所以,我有这样一个类方法

+(CGGradientRef)CreateGradient:(UIColor*)startColor endColor:(UIColor*)endColor { CGGradientRef result; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGFloat locations[2] = {0.0f, 1.0f}; CGFloat startRed, startGreen, startBlue, startAlpha; CGFloat endRed, endGreen, endBlue, endAlpha; [endColor getRed:&endRed green:&endGreen blue:&endBlue alpha:&endAlpha]; [startColor getRed:&startRed green:&startGreen blue:&startBlue alpha:&startAlpha]; CGFloat componnents[8] = { startRed, startGreen, startBlue, startAlpha, endRed, endGreen, endBlue, endAlpha }; result = CGGradientCreateWithColorComponents(colorSpace, componnents, locations, 2); CGColorSpaceRelease(colorSpace); return result; } 

及其用法。

 -(void)FillGradientRect:(CGRect)area startColor:(UIColor *)startColor endColor:(UIColor *)endColor isVertical:(BOOL)isVertical { CGContextRef context = UIGraphicsGetCurrentContext(); UIGraphicsPushContext(context); CGGradientRef gradient = [Graphics CreateGradient:startColor endColor:endColor]; CGPoint startPoint, endPoint; if (isVertical) { startPoint = CGPointMake(CGRectGetMinX(area), area.origin.y); endPoint = CGPointMake(startPoint.x, area.origin.y + area.size.height); }else{ startPoint = CGPointMake(0, area.size.height / 2.0f); endPoint = CGPointMake(area.size.width, startPoint.y); } CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0); CGGradientRelease(gradient); UIGraphicsPopContext(); } 

一切都按预期工作。 但是,当我从Xcode 4运行Analyze工具时,我在result变量的方法CreateGradient中收到有关内存泄漏的警告。 好吧,我理解那是什么,但在我的调用方法中,我正在释放渐变对象( CGGradientRelease(gradient); )。 那么,谁错了,如何让Analyze工具开心?

谢谢

由于CGGradientRef是Core Foundation类型的对象,因此您可以自动释放它。 只需在返回渐变之前添加此行:

 [(id)result autorelease]; 

如果目标仅仅是让分析仪在ARC中保持满意,那么只需将其设为C函数而不是Objective-C – 即:

 CGGradientRef CreateGradient(UIColor *startColor, UIColor * endColor) 

然后应用Core Foundation命名方案,该方案表示名称中包含Create的函数被视为返回保留对象(调用者有责任释放它)。 这满足了分析仪。

如果您想要一个自动释放的变量,那么将CG类型的所有权转移到ARC:

 id arc_result = (__bridge_transfer id)result 

但是,如果这样做,则需要返回objective-c类型(arc_result),而不是CG类型。 如果返回CG类型,则不会保留对arc_result的引用,因此编译器会在您从函数返回时清除它。

您可以使用此hack来实现CG类型的自动释放:

 dispatch_async(dispatch_get_main_queue(), ^{ CGGradientRelease(result); }); 

它会满足分析仪并可能工作 – 虽然我认为它是非常不安全的!