最早關(guān)注到這個問題是一位老前輩在分享如何面試一個合格的iOS開發(fā)上,提出來的:
"如何給一個UIImageView增加圓角过蹂?有幾種方法十绑?各自區(qū)別?"
這種問題酷勺,其實(shí)已經(jīng)有很多回答了本橙,這里只是簡單總結(jié)下,出于實(shí)踐優(yōu)先的原則脆诉,這里不會詳細(xì)解釋各個方法背后的原理甚亭,只是將常見的幾種方法做以簡單的對比,讓大家心里理清什么場景該用什么
備注:本文參考自cocoachina
UIImageView *poImgView = [[UIImageView alloc]init];
方案A(基本方案):
poImgView.layer.cornerRadius = poImgView.frame.size.width/2.0;
poImgView.layer.masksToBounds = YES;
(或者 poImgView.clipsToBounds = YES;)
備注:clipsToBounds是對view的切割击胜,masksToBounds是對layer的切割
性能消耗:
這個是離屏渲染(off-screen-rendering)亏狰,對性能消耗比較大
fps大致在45幀左右(每個cell 做2個imageview)
正常fps是60幀,越小偶摔,用戶體驗(yàn)越差
|
離屏渲染暇唾,指的是GPU在當(dāng)前屏幕緩沖區(qū)以外新開辟一個緩沖區(qū)進(jìn)行渲染操作。由上面的一個結(jié)論視圖和圓角的大小對幀率并沒有什么卵影響,數(shù)量才是傷害的核心輸出啊策州∪澄叮可以知道離屏渲染耗時是發(fā)生在離屏這個動作上面,而不是渲染够挂。為什么離屏這么耗時旁仿?原因主要有創(chuàng)建緩沖區(qū)和上下文切換。創(chuàng)建新的緩沖區(qū)代價都不算大孽糖,付出最大代價的是上下文切換枯冈。
方案B:
CAShapeLayer *layer = [CAShapeLayer layer];
UIBezierPath *aPath = [UIBezierPath bezierPathWithOvalInRect:aImageView.bounds];
layer.path = aPath.CGPath;
poImgView.layer.mask = layer;
性能消耗:
測試fps大致在20幀左右,比方案A的消耗更大
方案C:
- (UIImage *)imageWithCornerRadius:(CGFloat)radius {
CGRect rect = (CGRect){0.f, 0.f, self.size};
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;
}
性能消耗:
這個是on-screen-rendering
相當(dāng)于時時去做渲染办悟,相比于A.B方案的離線渲染尘奏,此方法對性能消耗最低,推薦用此方案誉尖。
說明
方案A和方案B都是比較常見的方式罪既,但是都不推薦,對此的優(yōu)化方案是是用C铡恕,但是如果費(fèi)用使用A或者B方案琢感,補(bǔ)救措施是:
self.layer.shouldRasterize = YES;
self.layer.rasterizationScale = [UIScreen mainScreen].scale;