问题
Sorry for noobish question about iPhone and Quartz programming. Just started my conversion from C++ to Objective-C :)
So, I have such a class method
+(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;
}
and its usage.
-(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();
}
everything works as expected. But, when I run the Analyze tool from Xcode 4, I'm getting a warning about memory leak in method CreateGradient for result
variable. Well, I understand what's that about, but in my calling method I'm releasing the gradient object (CGGradientRelease(gradient);
).
So, who is wrong and how to make Analyze tool happy?
Thx
回答1:
Since CGGradientRef is a Core Foundation type of object, you can autorelease it. Just add this line before returning the gradient:
[(id)result autorelease];
回答2:
If the goal is solely to keep the analyzer happy in ARC, then just make it a C function rather than objective-C - i.e.:
CGGradientRef CreateGradient(UIColor *startColor, UIColor * endColor)
The Core Foundation naming scheme then applies which says that a function with Create in the name is treated as returning a retained object (and it is the caller's responsibility to release it). This satisfies the analyser.
If you want an autoreleased variable, then transfer ownership of the CG type to ARC:
id arc_result = (__bridge_transfer id)result
However, if you do that, you need to return the objective-c type (arc_result), not the CG-type. If you return the CG type, there will be no retained references to arc_result, and so the compiler will clean it up as you return from the function.
You could use this hack to effect a CG-type autorelease:
dispatch_async(dispatch_get_main_queue(), ^{
CGGradientRelease(result);
});
It would satisfy the analyser and probably work - though I would consider it to be pretty unsafe!
来源:https://stackoverflow.com/questions/8032797/creating-gradient-and-returning-for-a-method