在开发过程中我们会经常遇到这种需求,而且面试的时候这个问题也会被经常问到,所以整理一下,做下记录。
一、大家都知道最直接的方法 CALayer的cornerRadius
self.imageView.layer.cornerRadius = 100;
self.imageView.clipsToBounds = YES;
这会造成离屏渲染(off-screen-rendering),是很耗性能的,会造成卡顿,有很多公司面试的时候会问到,希望大家注意一下。
离屏渲染:在使用圆角、阴影和遮罩等视图功能的时候,图层属性的混合体被指定为在未预合成之前不能直接在屏幕中绘制,所有就需要在屏幕外的上下文中渲染,即离屏渲染。
离屏渲染卡顿原因:离屏渲染之所以会特别消耗性能,是因为要创建一个屏幕外的缓冲区,然后从当屏缓冲区切换到屏幕外的缓冲区,然后再完成渲染;其中,创建缓冲区和切换上下文最消耗性能,而绘制其实不是性能损耗的主要原因。
备注:Apple 公司实际上早就发现了这个问题,所以,他们在 iOS 9 时修复了这个问题。所以,如果你的项目只需要适配 iOS 9 以及更高版本,可以用上面这个方法!网上所说的掉帧问题只在 iOS 9 之前才有,iOS 9 开始没有这个问题了!(这个大家可以测试一下)
二、下面介绍另一种方法绘图的方式(推荐使用这种方法)
给UIImage添加一个类别 实现一个方法
- (UIImage *)imageWithCornerRadius:(CGFloat)radius {
CGRect rect = (CGRect){0.f, 0.f, self.size};
// size——同UIGraphicsBeginImageContext,参数size为新创建的位图上下文的大小
// opaque—透明开关,如果图形完全不用透明,设置为YES以优化位图的存储。
// scale—–缩放因子
UIGraphicsBeginImageContextWithOptions(self.size, NO, UIScreen.mainScreen.scale);
// 根据矩形画带圆角的曲线
CGContextAddPath(UIGraphicsGetCurrentContext(),
[UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius].CGPath);
CGContextClip(UIGraphicsGetCurrentContext());
[self drawInRect:rect];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// 关闭上下文
UIGraphicsEndImageContext();
return image;
}