平時代碼中用cornerRadius和masksToBounds兩個屬性裁出圓角,這樣雖然簡單,但會由于離屏渲染(Off-Screen Rendering),會產(chǎn)生性能問題。一篇對離屏渲染研究的文章http://www.itdecent.cn/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), ^{
/**
* 創(chuàng)建一個基于位圖的上下文(context),并將其設(shè)置為當(dāng)前上下文(context)
* size——同UIGraphicsBeginImageContext
* opaque—透明開關(guān),如果圖形完全不用透明,設(shè)置為YES以優(yōu)化位圖的存儲。
* 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調(diào)用addClip之后,它所在的context的可見區(qū)域就變成了它的“fill area”,接下來的繪制,如果在這個區(qū)域外都會被無視。
[beziPath addClip];
[image drawInRect:imageView.bounds];
UIImage *processedImageRef = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
dispatch_async(dispatch_get_main_queue(), ^{
imageView.image = processedImageRef;
});
});
}