Сбой приложения при использовании __bridge для градиента CoreGraphics на ARC - PullRequest
2 голосов
/ 01 апреля 2012

Я создаю приложение для 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.Что именно вызывает проблему?

Ответы [ 2 ]

4 голосов
/ 03 апреля 2012

Я столкнулся с точно такой же проблемой. Я прибег к использованию CGGradientCreateWithColorComponents, который решает проблему для меня. Вы должны преобразовать ваш NSArray CGColorRef s в массив 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);
3 голосов
/ 07 апреля 2012

Возможно, ваша проблема связана с временем жизни переменных startColor и т. Д. Я предполагаю, что это могут быть CGColorRefs, созданные с помощью метода -CGColor UIColor в некотором месте над кодом, который вы перечислили.

Как я опишу в этом ответе , если вы явно не сохраните эти CGColorRef, они могут исчезнуть после того, как UIColor, который их сгенерировал, был освобожден. Учитывая, что вы никогда больше не будете использовать UIColors после того, как извлечете из них CGColorRef, ARC может принять решение об освобождении этих UIColors, прежде чем вы сможете использовать CGColorRef. Я видел, что время жизни объектов в симуляторе и реальных устройствах различается, поэтому это может объяснить сбой одного, но не другого.

Мое решение для этого было использовать немедленное приведение к 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, оставляя после себя CFArrayRef с счетом сохранения не менее 1. Затем вы можете использовать это в своем создании градиента, где градиент, как мы надеемся, сохранит ссылку на него, и освободить его вручную. когда закончите.

Однако предложение Bringo полностью работать в API-интерфейсе Core Graphics для этого может быть самым простым способом. Я просто подумал, что объясню потенциальный источник ваших проблем на случай, если вы столкнетесь с чем-то похожим в будущем.

...