renderInContext 时 CAGradientLayer 消失
我已经尝试/搜索了几天来让它发挥作用,但没有成功。我不确定我错过了什么。
我正在创建一个“卡片”前视图并添加到 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;
以及 renderInContext 的代码:
- (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];
I've been trying/searching for a few days to get this to work to no avail. I'm not sure what I'm missing.
I'm creating a "card" front view and adding to UIView layer. On screen everything looks great, when calling renderInContext one layer will not display.
EDIT: Wanted to add that only the "highlight" gradient layer is not working the other gradient layer is working as expected.
- (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;
And the code to renderInContext:
- (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];
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
感谢您发布您的代码,它使帮助变得更加容易:)
一些误解......
这一行是错误的。
[CALayer layer]
返回一个完全形成的层,调用init
可能会对该层执行一些“有趣”的操作。一般来说,当您调用返回新实例的类方法(alloc
除外)时,您永远不应该调用 init。另外,下面代码中的调用将导致崩溃(如果曾经执行过,请参见下文)。
由于方法
layer
名称中没有“copy”、“new”或“alloc”,因此它返回一个不应释放的对象。该图层将“自动释放”返回,因此您不会保留该图层。请在此处阅读 ObjC 内存管理指南
了解更多信息。
另外,你应该听编译器的声音,当它告诉你那些释放调用无法到达时,这就是意思。
return
之后什么都不会执行。一般来说,您不应该将图像放入数据库中,除非它们非常小(小于几十千字节)。请查看此处
了解更多信息有关该主题的信息。
至于为什么不绘制渐变,可能是不同的颜色空间,但这似乎不是问题。
我想说至少尝试清理双重
init
问题和内存问题,然后重试。Thanks for posting your code, it makes it much easier to help :)
A couple of misunderstandings...
This line is wrong.
[CALayer layer]
returns a fully formed layer, callinginit
is probably doing some 'interesting' things to the layer. In general when you call a class method that returns a new instance (apart fromalloc
) you should never call init.Also this call below in the code will lead to a crash (if it were ever executed, see below).
Since the method
layer
does not have 'copy', 'new' or 'alloc' in the name it is returning an object that you should not release. The layer is returned 'autoreleased' and is thus not retained by you.Please read the ObjC memory management guide here
for more info.
Also, you should listen to the compiler, when it tells you those release calls can't be reached, it means it. After the
return
nothing will be executed.In general you should never put image's into the database, unless they are really small (less than a few dozen kilobytes). Take a look here
for more info on that topic.
As to why it's not drawing the gradient, it could be different color spaces, but that does not appear to be the problem.
I'd say try cleaning up at least the double
init
issue and the memory problems then try again.幸运的是,我似乎能够通过简单地更改 CAGradientLayer 颜色数组的值来解决我的问题。
我
会假设 [UIColor WhiteColor] 和 RGBACOLOR(255,255,255, 1.0) 本质上是相同的,但 renderInContext 不这么认为。
Appears, by luck, I was able to get my problem solved by simply changing the values of my CAGradientLayer colors array.
to
I would have assumed that [UIColor whiteColor] and RGBACOLOR(255,255,255, 1.0) are essentially the same, renderInContext doesn't think so.