CAGradientLayer исчезает, когда renderInContext - PullRequest
1 голос
/ 24 марта 2011

Я пытался / искал несколько дней, чтобы заставить это работать безрезультатно. Я не уверен, что мне не хватает.

Я создаю "карточный" вид спереди и добавляю в слой UIView. На экране все выглядит отлично, при вызове renderInContext один слой не будет отображаться.

РЕДАКТИРОВАТЬ: Хотелось бы добавить, что только градиентный слой «выделение» не работает, другой градиентный слой работает как положено.

- (CALayer *)createCardFront {

NSLog(@"Card createCardFront Called");

// Create the layers we want to use

CALayer *cardFrontContainer = [CALayer layer];
CALayer *processedImage = [CALayer layer];
CAGradientLayer *gradient = [CAGradientLayer layer];
CAGradientLayer *hightlight = [CAGradientLayer layer];
CALayer *icon = [CALayer layer];
CAShapeLayer *gloss = [CAShapeLayer layer];

// Position them correctly

[cardFrontContainer addSublayer:processedImage];
[cardFrontContainer addSublayer:gradient];
[cardFrontContainer addSublayer:hightlight];
[cardFrontContainer addSublayer:icon];
[cardFrontContainer addSublayer:gloss];


// Base size for card

CGRect rect = CGRectMake(0., 0., (200. * [cardScale floatValue]), (276. * [cardScale floatValue]));

// Container Properties

cardFrontContainer.bounds = rect;
cardFrontContainer.position = CGPointMake((frontView.center.x * [cardScale floatValue]), (138. * [cardScale floatValue])-10);
cardFrontContainer.cornerRadius = (25. * [cardScale floatValue]);
cardFrontContainer.masksToBounds = YES;
cardFrontContainer.borderWidth = .5;
cardFrontContainer.borderColor = [RGBACOLOR(120,120,120, .7) CGColor];
[cardFrontContainer setNeedsDisplay];

// Highlight Properites

hightlight.bounds = rect;
hightlight.position = CGPointMake((100. * [cardScale floatValue]), (138. * [cardScale floatValue]));
hightlight.startPoint = CGPointMake(0., 0.0);
hightlight.endPoint = CGPointMake(0., 1.);
hightlight.opacity = 1.;
hightlight.locations = [NSArray arrayWithObjects:[NSNumber numberWithFloat:.0111],
                        [NSNumber numberWithFloat:.0999],
                        [NSNumber numberWithFloat:1.], nil];

hightlight.colors = [NSArray arrayWithObjects:(id)[[UIColor whiteColor] CGColor],
                     (id)[RGBACOLOR(255,255,255, .0) CGColor],
                     (id)[RGBACOLOR(255,255,255, .0) CGColor], nil];


// Gradient Properites

gradient.bounds = rect;
gradient.position = CGPointMake((100. * [cardScale floatValue]), (138. * [cardScale floatValue]));
gradient.startPoint = CGPointMake(0, 0.5);
gradient.endPoint = CGPointMake(1.0, 0.5);
gradient.opacity = 1.;
gradient.locations = [NSArray arrayWithObjects:[NSNumber numberWithFloat:.0111],
                            [NSNumber numberWithFloat:.099],
                            [NSNumber numberWithFloat:.899],
                            [NSNumber numberWithFloat:.9999], nil];

gradient.colors = [NSArray arrayWithObjects:(id)[RGBACOLOR(0,0,0, .3) CGColor],
                         (id)[[UIColor clearColor] CGColor],
                         (id)[[UIColor clearColor] CGColor],
                         (id)[RGBACOLOR(0,0,0, .3) CGColor], nil];



// Background Properites

processedImage.bounds = rect;
processedImage.position = CGPointMake((100. * [cardScale floatValue]), (138. * [cardScale floatValue]));
processedImage.contents = (id)[cachedBackground CGImage];


// Icon Properites

iconImage = [[self processThumbnailImageForLayer] retain];

icon.bounds = CGRectMake(0., 0., (200 * [cardScale floatValue]), (276 * [cardScale floatValue]));
icon.position = CGPointMake((100. * [cardScale floatValue]), (138. * [cardScale floatValue]));
icon.contents = (id)[iconImage CGImage];



// Set the Gloss Layer

gloss.frame = CGRectMake(0., 0., (200. * [cardScale floatValue]), (200. * [cardScale floatValue]));
gloss.position = CGPointMake(0.,0.);
CGMutablePathRef thePath = CGPathCreateMutable();
CGPathMoveToPoint(thePath,NULL,(100. * [cardScale floatValue]),(350. * [cardScale floatValue]));
CGPathAddLineToPoint(thePath, NULL, (100. * [cardScale floatValue]), (100. * [cardScale floatValue]));
CGPathAddLineToPoint(thePath, NULL, (270. * [cardScale floatValue]), (100. * [cardScale floatValue]));
CGPathAddCurveToPoint(thePath,NULL,
                      (200. * [cardScale floatValue]),(140. * [cardScale floatValue]),
                      (100. * [cardScale floatValue]),(245. * [cardScale floatValue]),
                      (100. * [cardScale floatValue]),(376. * [cardScale floatValue]));
CGPathCloseSubpath(thePath);
gloss.path = thePath;
CGPathRelease(thePath);
gloss.opacity = .3;
gloss.fillColor = [[UIColor whiteColor] CGColor];


return cardFrontContainer;

И код для рендерингаInContext:

- (void) imageFromView {

NSLog(@"Card imageFromView Called");

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];



UIGraphicsBeginImageContext(CGSizeMake(170., 238.));
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

NSData *imageData = UIImagePNGRepresentation (viewImage);

// Add to core data object

attributeObject.cardCache = imageData;
attributeObject.shouldUpdateCard = NO;

[self saveAction];

[self.managedObjectContext reset];
 self.managedObjectContext = nil;

[pool release];

Ответы [ 2 ]

4 голосов
/ 24 марта 2011

Спасибо за размещение вашего кода, это значительно облегчает помощь:)

Пара недоразумений ...

CALayer *cardFrontContainer = [[CALayer layer] init];

Эта строка неверна. [CALayer layer] возвращает полностью сформированный слой, вызов init, вероятно, делает некоторые "интересные" вещи для слоя. В общем, когда вы вызываете метод класса, который возвращает новый экземпляр (кроме alloc), вы никогда не должны вызывать init.

Также этот вызов ниже в коде приведет к падению (если он когда-либо выполнялся, см. Ниже).

[cardFrontContainer release]

Так как метод layer не имеет в названии «copy», «new» или «alloc», он возвращает объект, который вы не должны освобождать. Слой возвращается как «автоматически выпущенный» и поэтому не сохраняется вами.

Пожалуйста, прочитайте руководство по управлению памятью ObjC здесь

для получения дополнительной информации.

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

Как правило, вы никогда не должны помещать изображения в базу данных, если они не очень маленькие (менее нескольких десятков килобайт). Взгляните здесь

для получения дополнительной информации по этой теме.

Относительно того, почему он не рисует градиент, это могут быть разные цветовые пространства, но это не проблема.

Я бы сказал, попробуйте устранить хотя бы двойную проблему init и проблемы с памятью, затем повторите попытку.

2 голосов
/ 24 марта 2011

Похоже, мне повезло, что я смог решить мою проблему, просто изменив значения моего массива цветов CAGradientLayer.

hightlight.colors = [NSArray arrayWithObjects:(id)[[UIColor whiteColor] CGColor],
                 (id)[RGBACOLOR(255,255,255, .0) CGColor],
                 (id)[RGBACOLOR(255,255,255, .0) CGColor], nil];

до

hightlight.colors = [NSArray arrayWithObjects:(id)[RGBACOLOR(255,255,255, 1.0) CGColor],
                 (id)[RGBACOLOR(255,255,255, .0) CGColor],
                 (id)[RGBACOLOR(255,255,255, .0) CGColor], nil];

Я бы предположил, что [UIColor whiteColor] и RGBACOLOR (255,255,255, 1.0) по сути одинаковы, renderInContext так не считает.

...