首先標(biāo)題是隨性創(chuàng)造,如有雷同純屬巧合罩驻!為什么要寫這篇文章?最近在搞xamarin開發(fā),做個(gè)控件圓角難做得蛋疼表窘。很是懷念OC的實(shí)現(xiàn)。然后一個(gè)興起做了這個(gè)評(píng)測(cè)纱耻。
本評(píng)測(cè)主要是探討在多種方式下實(shí)現(xiàn)iOS圓角的實(shí)現(xiàn)领突,對(duì)FPS(frames per second ==幀每秒)的影響。
先來來個(gè)對(duì)比:請(qǐng)問案例一卡頓還是案例二卡頓?
答案就是:答案自找
ok琳袄,先來說說畫圓角的方式:
1. 使用layer江场,這應(yīng)該是我們最常用的方法了,兩代碼解決戰(zhàn)斗窖逗。
view.layer.masksToBounds = YES; ```
上圖:


可以從圖中知道址否,在滑動(dòng)tableview時(shí),fps只有18碎紊、19(正常60)佑附。這種狀態(tài)有個(gè)俗語:“卡出翔”。
簡(jiǎn)略代碼:
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"threeCell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"threeCell"];
...
...
UIImageView * view = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"hehe"]];
view.frame = CGRectMake(0, 0, 44, 44);
view.layer.cornerRadius = 22;
view.layer.masksToBounds = YES;
// view.layer.shouldRasterize = YES;
// view.layer.rasterizationScale = [UIScreen mainScreen].scale;
[cell addSubview:view];
...
我們得想辦法優(yōu)化ho矮慕,然后Google了下就有了上面注釋的兩行代碼帮匾。
想必大家也留意到這兩行代碼
// view.layer.shouldRasterize = YES;
// view.layer.rasterizationScale = [UIScreen mainScreen].scale;
加上以后,大家可以看看效果痴鳄。

更加卡了瘟斜,怎么辦呢?為啥呢痪寻?
其實(shí)這兩句話不應(yīng)該放在這個(gè)地方螺句,應(yīng)該在cell.layer上面添加。
cell.layer.shouldRasterize = YES;
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;
修改了地方以后橡类,我們?cè)倏纯葱Ч?
添加這兩句代碼后蛇尚,能將你的幀數(shù)提高到50以上,```shouldRasterize = YES```會(huì)使視圖渲染內(nèi)容被緩存起來顾画,下次繪制的時(shí)候可以直接顯示緩存取劫。但這的前提是得保證內(nèi)容不變的情況下。如果你的圖片是變化的研侣,這可能也會(huì)對(duì)性能造成影響谱邪。
##2.drawrect
UIImage * myImage = [UIImage imageNamed:@"hehe"];
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSaveGState(ctx);//保存上下文
CGContextAddEllipseInRect(ctx,CGRectMake(105, 5, 40, 40));//因?yàn)橹灰_定了矩形框,圓或者是橢圓就確定了庶诡。
CGContextClip(ctx);
CGContextTranslateCTM(ctx, 0, 50);
CGContextScaleCTM(ctx, 1, -1);
CGContextDrawImage(ctx, CGRectMake(100, 0, 50, 50), [myImage CGImage]);
CGContextRestoreGState(ctx);//恢復(fù)狀態(tài)后惦银,就不會(huì)受裁剪的影響,不然只能在剪裁


從圖中可以分析得出末誓,使用drawrect方式來實(shí)現(xiàn)圓角扯俱,F(xiàn)PS會(huì)比較高,基本不會(huì)卡頓喇澡。而CPU的使用情況也是可以接受的迅栅。
##3.UIBezierPath,貝塞爾曲線
UIImageView * view = [[UIImageView alloc] init];
view.frame = CGRectMake(200, 0, 44, 44);
[cell addSubview:view];
UIImage * image = [UIImage imageNamed:@"hehe"];
UIGraphicsBeginImageContextWithOptions(CGSizeMake(44, 44), NO, 1.0);
[[UIBezierPath bezierPathWithRoundedRect:view.bounds cornerRadius:22] addClip];
[image drawInRect:view.bounds];
view.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();


使用貝塞爾曲線來做這個(gè)功能晴玖,CPU使用情況比drawrect的方式要高一些库继,但也沒有很高的狀態(tài)箩艺。
dispatch_queue_t Cricle = dispatch_queue_create("ImageCreate1", NULL);
dispatch_async(Cricle, ^{
UIImage * image = [UIImage imageNamed:@"hehe"];
UIGraphicsBeginImageContextWithOptions(CGSizeMake(44, 44), NO, 1.0);
[[UIBezierPath bezierPathWithRoundedRect:view.bounds cornerRadius:22] addClip];
[image drawInRect:view.bounds];
UIImage * doneImage = UIGraphicsGetImageFromCurrentImageContext();
dispatch_async(dispatch_get_main_queue(), ^{
view.image = doneImage;
});
UIGraphicsEndImageContext();
});
使用一個(gè)子線程去渲染圖片窜醉,然后在主線程更新UI宪萄,這方法在如果只渲染一張圖片速度還是挺快的,cpu和fps都沒啥問題榨惰。但一個(gè)cell中有4個(gè)這樣的圖片拜英,手機(jī)就不行了。

CPU處于滿載狀態(tài)琅催,一開始fps還有50+居凶,慢慢就變成只有20-30了。所以不推薦這個(gè)藤抡,還是簡(jiǎn)單粗暴比較好侠碧。(若是我打開姿勢(shì)不對(duì),請(qǐng)立馬留意)
##4.Mask缠黍,很有趣的方法
cell.layer.shouldRasterize = YES;
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;
...
...
UIImageView * view = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"hehe"]];
view.frame = CGRectMake(0, 0, 44, 44);
[cell addSubview:view];
CALayer *maskLayer = [CALayer layer];
maskLayer.frame = view.bounds;
maskLayer.contents = (id)[UIImage imageNamed:@"xingxing"].CGImage;
view.layer.mask = maskLayer;
先看圖


這實(shí)現(xiàn)效果和layer.cornerRadius相類似弄兜,但Mask的性能比layer.cornerRadius要低。不過優(yōu)點(diǎn)是你可以將你的圖片變成任何形狀的圖形瓷式。
> 總結(jié):
1.如果你的內(nèi)容不多變替饿,并且當(dāng)前頁面不卡頓∶车洌可以使用layer.cornerRadius+ layer.shouldRasterize來實(shí)現(xiàn)视卢。
2.如果你當(dāng)前頁面需要優(yōu)化性能,并且內(nèi)容是變化的廊驼,推薦使用貝塞爾曲線來實(shí)現(xiàn)据过。
3.drawrect方法會(huì)造成離屏渲染,當(dāng)點(diǎn)擊cell或者頁面有內(nèi)容更新的時(shí)候就會(huì)重新調(diào)用妒挎,會(huì)造成不必要的性能損耗绳锅。
ps:有些人會(huì)在圖片上面覆蓋一個(gè)鏤空?qǐng)A形圖片的方法可以實(shí)現(xiàn)圓形頭像效果,這個(gè)雖然是個(gè)極為高效的方法饥漫。但我的想法是——

這里是github連接:
https://github.com/ouzhenxuan/DrawCircle
喜歡請(qǐng)點(diǎn)個(gè)贊。