Создание градиента и возврат для метода - PullRequest
3 голосов
/ 07 ноября 2011

Извините за нубистский вопрос о программировании iPhone и Quartz. Только что начал свое преобразование из 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, я получаю предупреждение об утечке памяти в методе CreateGradient для result переменной. Хорошо, я понимаю, о чем это, но в моем вызывающем методе я освобождаю объект градиента (CGGradientRelease(gradient);). Итак, кто же не прав и как сделать инструмент Analyze счастливым?

Thx

Ответы [ 2 ]

1 голос
/ 07 ноября 2011

Поскольку CGGradientRef является базовым типом объекта, вы можете автоматически выпустить его. Просто добавьте эту строку перед возвратом градиента:

[(id)result autorelease];
0 голосов
/ 22 сентября 2014

Если цель состоит только в том, чтобы анализатор был доволен в ARC, то просто сделайте его функцией C, а не target-C - т.е.

CGGradientRef CreateGradient(UIColor *startColor, UIColor * endColor)

Затем применяется схема именования Core Foundation, в которой говорится, что функция с Create в имени рассматривается как возвращающая сохраненный объект (и вызывающая сторона несет ответственность за его освобождение). Это удовлетворяет анализатор.

Если вам нужна переменная с автоматическим выпуском, передайте право собственности на тип CG на ARC:

id arc_result = (__bridge_transfer id)result

Однако, если вы это сделаете, вам нужно будет вернуть тип target-c (arc_result), а не CG-тип. Если вы вернете тип CG, не будет сохраненных ссылок на arc_result, и поэтому компилятор очистит его, когда вы вернетесь из функции.

Вы можете использовать этот хак для выполнения автоматического выпуска CG-типа:

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

Это удовлетворит анализатор и, вероятно, сработает - хотя я бы посчитал его довольно небезопасным!

...