******阅读完此文,大概需要3分钟******
业务开发中常常需要截屏生成一张UIView的Image,我们前期就做了一个需要对UIView进行截屏的需求,iOS上截屏的方案有多种,因为我们需要控制图片的分辨率,防止图片过大,所以我们采取了两种方案对UIView进行截屏;
第一种:renderInContext方式,主要代码如下:
- (UIImage *)convertViewToImage:(UIView *)v { @autoreleasepool { CGSize s = CGSizeMake(v.width, v.height); UIGraphicsBeginImageContextWithOptions(s, NO, 2); [v.layer renderInContext:UIGraphicsGetCurrentContext()]; v.layer.contents = nil; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image; } }记住,当我们把UIView的layer渲染完以后,Layer的contents可以提前释放,这样有利于降低内存峰值。这种截屏方案的原理也有介绍:
/** Rendering properties and methods. **/
/* Renders the receiver and its sublayers into 'ctx'. This method
* renders directly from the layer tree. Renders in the coordinate space
* of the layer.
*
* WARNING: currently this method does not implement the full
* CoreAnimation composition model, use with caution. */
renderInContext:方式实际上是通过遍历UIView的layer tree进行渲染,但是它不支持动画的渲染,它的的性能会和layer tree的复杂度直接关联。第二种:UISnapshotting方式,代码如下:
- (UIImage *)convertViewToImage:(UIView *)v { @autoreleasepool { CGSize s = CGSizeMake(v.width, v.height); UIGraphicsBeginImageContextWithOptions(s, NO, 2); [v drawViewHierarchyInRect:v.frame afterScreenUpdates:YES]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image; } }drawViewHierarchyInRect:afterScreenUpdates:的api是苹果基于UIView的扩展,与第一种方式不同,这种方式是直接获取当前屏幕的“快照”,
所以,此种方式的性能与UIView的frame大小直接关联。
以下是我做的几组性能测试数据:
在UIView内容不是很“长”的情况下,第二种方式有内存优势的;但是随着UIView的内容增加,第二种方式会有较大增加;
第二种因为需要等到UIView的update结束才会去capture,所以时间会慢些。
(以上数据会随着你的测试平台和机型不同,仅供参考。)