平时代码中用cornerRadius和masksToBounds两个属性裁出圆角,这样虽然简单,但会由于离屏渲染(Off-Screen Rendering),会产生性能问题。一篇对离屏渲染研究的文章http://www.jianshu.com/p/6d24a4c29e18
高效裁剪的方法是:切换到工作线程利用CoreGraphic API生成一个offscreen UIImage,再切换到main thread赋值给UIImageView。
- (void)cornerRadiusWithImage:(UIImage *)image imageView:(UIImageView *)imageView UIColor:(UIColor *)color{
CGSize size = imageView.bounds.size;
CGFloat scale = [UIScreen mainScreen].scale;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
/**
* 创建一个基于位图的上下文(context),并将其设置为当前上下文(context)
* size——同UIGraphicsBeginImageContext
* opaque—透明开关,如果图形完全不用透明,设置为YES以优化位图的存储。
* scale—–缩放因子
*/
UIGraphicsBeginImageContextWithOptions(size, YES, scale);
CGContextRef currentContext = UIGraphicsGetCurrentContext();
if (nil == currentContext) {
return;
}
UIBezierPath *beziPath = [UIBezierPath bezierPathWithRoundedRect:imageView.bounds cornerRadius:imageView.bounds.size.height/2];
UIBezierPath *backgroundRect = [UIBezierPath bezierPathWithRect:imageView.bounds];
[color setFill];
[backgroundRect fill];
//简单的说,就是一个path调用addClip之后,它所在的context的可见区域就变成了它的“fill area”,接下来的绘制,如果在这个区域外都会被无视。
[beziPath addClip];
[image drawInRect:imageView.bounds];
UIImage *processedImageRef = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
dispatch_async(dispatch_get_main_queue(), ^{
imageView.image = processedImageRef;
});
});
}