[英]“[CALayer renderInContext]” crashes on iPhone X
我有一个自定义UIView
,我想呈现为UIImage
。 自定义UIView
是UIImageView
的子类。
在此视图内,我正在渲染一些UI元素(在图像上绘制一堆圆圈)。 添加的圈子数量可以达到数千个。
我正在使用这个简单的代码片段将视图呈现为UIImage
:
// Create the UIImage (code runs on the main thread inside an @autorelease pool)
UIGraphicsBeginImageContextWithOptions(viewToSave.image.size, viewToSave.opaque, 1.0);
[viewToSave.layer renderInContext:UIGraphicsGetCurrentContext()];
imageToSave = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Since I'm rendering some stuff inside the .layer of the UIView,
// I don't think I can use "drawViewHierarchyInRect: afterScreenUpdates:"
这是从Instruments中获取的内存分配,在示例中,添加了约3000个圆圈作为子视图:
现在,这里是奇怪的部分...运行良好,我可以多次(连续)渲染图像并将其保存在iPhone 5,iPhone 5s,iPhone 6s,iPad Air 2,iPad Mini 4等设备的图像库中。 。但是相同的代码会触发iPhone X上的内存警告,并最终导致应用程序崩溃...
不幸的是,我没有iPhone X的访问权限,而报告此举的人也没有Mac的访问权限,因此我无法进行更深入的研究。
我真的不知道我做错什么了吗...您知道iPhone X是否有所不同吗? 我已经为这个问题苦苦挣扎了一段时间了...
我想这个问题与CALayer:renderInContext:
如何在需要按比例放大的上下文中处理成千上万个视图的绘制有关。 可以尝试自己渲染子视图吗? 然后通过使用仪器比较并验证它是否更好。
UIImage *imageToSave = [self imageFromSubLayer:viewToSave];
- (UIImage *)imageFromSubLayers:(UIImageView *)imageView {
CGSize size = imageView.image.size;
UIGraphicsBeginImageContextWithOptions(size, YES, .0);
CGContextRef context = UIGraphicsGetCurrentContext();
for (CALayer *layer in imageView.layer.sublayers)
[layer renderInContext:context];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
我最近在我制作的应用程序中编写了一种方法,用于将UIView转换为UIImages(这样我就可以在进度视图/选项卡栏上显示渐变)。 我最终解决了以下代码,我使用此代码来渲染选项卡按钮,它适用于包括X在内的所有设备。
目标C:
UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:gradientView.bounds.size];
UIImage *gradientImage = [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) {
[gradientView drawViewHierarchyInRect:gradientView.bounds afterScreenUpdates:true];
}];
斯威夫特4:
let renderer = UIGraphicsImageRenderer(size: gradientView.bounds.size)
let image = renderer.image { ctx in
gradientView.drawHierarchy(in: gradientView.bounds, afterScreenUpdates: true)
}
我在编写的示例项目中使用了此代码,这是项目文件的链接:
如您所见,这两个项目都将在iPhone X上完美运行!
我知道,以下听起来很奇怪。 但是,请尝试使目标图像比要绘制的像素大一像素。 这为我解决了(我的特殊问题: “ [CALayer renderInContext]”在iPhone X上崩溃 )。
在代码中:
UIGraphicsBeginImageContextWithOptions(
CGSizeMake(viewToSave.image.size.width + 1,
viewToSave.image.size.height + 1),
viewToSave.opaque,
1.0
);
总而言之,答案在于最小的问题(不包括在问题中)...
我真的没有考虑过(不久后才发现), iPhone X的缩放系数等于@ 3x 。 这就是iPhone X和其他所有正在运行该代码的设备之间的区别...
在代码的某个时刻,我将子视图的.contentScaleFactor
设置为等于[UIScreen mainScreen].scale
。 这意味着在高端设备上,图像质量应该更好。
对于iPhone X, [UIScreen mainScreen].scale
返回3。对于我测试过的所有其他设备, [UIScreen mainScreen].scale
返回2。这意味着在iPhone X上,用于渲染屏幕的内存量[UIScreen mainScreen].scale
。图像要高得多。
有趣的事实二:从另一篇有用的SO文章中 ,我发现在iPhone X上,如果您尝试分配的内存总量(1392 MB)超过50%,则会崩溃。 另一方面,例如,在iPhone 6s的情况下,百分比更高:68%(1396 MB)。 这意味着与iPhone X相比,对于某些较旧的设备,您拥有更多的工作记忆。
对不起,我误导了我,这是一个诚实的错误。 谢谢大家的答案!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.