iOS圖片設(shè)置圓角性能問題

一般我們?cè)趇OS開發(fā)的過程中設(shè)置圓角都是如下這樣設(shè)置的。

 avatarImageView.clipsToBounds = YES;
 [avatarImageView.layer setCornerRadius:50];

這樣設(shè)置會(huì)觸發(fā)離屏渲染,比較消耗性能。比如當(dāng)一個(gè)頁面上有十幾頭像這樣設(shè)置了圓角會(huì)明顯感覺到卡頓。

注意:png圖片UIImageView處理圓角是不會(huì)產(chǎn)生離屏渲染的。(ios9.0之后不會(huì)離屏渲染,ios9.0之前還是會(huì)離屏渲染)。

設(shè)置圓角的方法

直接使用setCornerRadius
這種就是最常用的,也是最耗性能的。
setCornerRadius設(shè)置圓角之后,shouldRasterize=YES光柵化

avatarImageView.clipsToBounds = YES;
[avatarImageView.layer setCornerRadius:50];
avatarImageView.layer.shouldRasterize = YES;
avatarImageViewUrl.layer.rasterizationScale=[UIScreen mainScreen].scale;  //UIImageView不加這句會(huì)產(chǎn)生一點(diǎn)模糊 

shouldRasterize=YES設(shè)置光柵化,可以使離屏渲染的結(jié)果緩存到內(nèi)存中存為位圖,
使用的時(shí)候直接使用緩存,節(jié)省了一直離屏渲染損耗的性能。
但是如果layer及sublayers常常改變的話,它就會(huì)一直不停的渲染及刪除緩存重新
創(chuàng)建緩存,所以這種情況下建議不要使用光柵化,這樣也是比較損耗性能的。
直接覆蓋一張中間為圓形透明的圖片(推薦使用)
這種方法就是多加了一張透明的圖片,GPU計(jì)算多層的混合渲染 blending也是會(huì)消耗
一點(diǎn)性能的,但比第一種方法還是好上很多的。
UIImage drawInRect繪制圓角
這種方式GPU損耗低內(nèi)存占用大,而且UIButton上不知道怎么繪制,可以用
UIimageView添加個(gè)點(diǎn)擊手勢(shì)當(dāng)做UIButton使用。

UIGraphicsBeginImageContextWithOptions(avatarImageView.bounds.size, NO, [UIScreen mainScreen].scale);
[[UIBezierPath bezierPathWithRoundedRect:avatarImageView.bounds
cornerRadius:50] addClip];
[image drawInRect:avatarImageView.bounds];
avatarImageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

這段方法可以寫在SDWebImage的completed回調(diào)里,在主線程異步繪制。
也可以封裝到UIImageView里,寫了個(gè)DSRoundImageView。后臺(tái)線程異步繪制,不會(huì)阻塞主線程。

問題:這種方法圖片很多的話CUP消耗會(huì)高,內(nèi)存占用也會(huì)暴增,而且后臺(tái)線程繪制會(huì)比在主線程繪制占用更多的內(nèi)存,不知道怎么解決?求大神指教!
SDWebImage處理圖片時(shí)Core Graphics繪制圓角

//UIImage繪制為圓角
int w = imageSize.width;
int h = imageSize.height;
int radius = imageSize.width/2;
UIImage *img = image;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, w, h, 8, 4 * w, colorSpace, kCGImageAlphaPremultipliedFirst);
CGRect rect = CGRectMake(0, 0, w, h);
CGContextBeginPath(context);
addRoundedRectToPath(context, rect, radius, radius);
CGContextClosePath(context);
CGContextClip(context);
CGContextDrawImage(context, CGRectMake(0, 0, w, h), img.CGImage);
CGImageRef imageMasked = CGBitmapContextCreateImage(context);
img = [UIImage imageWithCGImage:imageMasked];
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
CGImageRelease(imageMasked);

以上代碼我寫成了UIImage的類別:UIImage+DSRoundImage.h
并在SDWebImage庫(kù)里處理image的時(shí)候使用類別方法繪制圓角并緩存。

使用Instruments的Core Animation查看性能
Color Offscreen-Rendered Yellow
開啟后會(huì)把那些需要離屏渲染的圖層高亮成黃色,這就意味著黃色圖層可能存在性能問題。
Color Hits Green and Misses Red
如果shouldRasterize被設(shè)置成YES,對(duì)應(yīng)的渲染結(jié)果會(huì)被緩存,如果圖層是綠色,就表示這些緩存被復(fù)用;如果是紅色就表示緩存會(huì)被重復(fù)創(chuàng)建,這就表示該處存在性能問題了。
用Instruments測(cè)試得
第一種方法,UIImageView和UIButton都高亮為黃色。
第二種方法,UIImageView和UIButton都高亮為綠色
第三種方法,無任何高亮,說明沒離屏渲染。
這種圓片覆蓋的方法一般只用在底色為純色的時(shí)候,如果圓角圖片的父View是張圖片的時(shí)候就沒辦法了,而且底色如果是多種顏色的話那要做多張不同顏色的圓片覆蓋。(可以用代碼取底色的顏色值給圓片著色)
第四種方法無任何高亮,說明沒離屏渲染(但是CPU消耗和內(nèi)存占用會(huì)很大)
第五種方法無任何高亮,說明沒離屏渲染,而且內(nèi)存占用也不大。(暫時(shí)感覺是最優(yōu)方法)
問題回復(fù):
有回復(fù)提到還有一種mask方法。
這種方法比第一種方法其實(shí)更卡頓。一次mask發(fā)生了兩次離屏渲染和一次主屏渲染。 具體可以參考小心別讓圓角成了你列表的幀數(shù)殺手
@nerozhao說第四種比第一種更卡。
我剛在demo里加了個(gè)例子測(cè)試了一下,第一種能明顯的感覺到卡頓,第四種還是挺順暢
的,有興趣的可以自己試試看。第四種是解決了離屏渲染GPU的問題。
可以用Instruments的 GPU Driver進(jìn)行測(cè)試:
Renderer Utilization
如果這個(gè)值超過了~50%,就意味著你的動(dòng)畫可能對(duì)幀率有所限制,很可能因?yàn)殡x屏渲染或者是重繪導(dǎo)致的過度混合。
Tiler Utilization
如果這個(gè)值超過了~50%,就意味著你的動(dòng)畫可能限制于幾何結(jié)構(gòu)方面,也就是在屏幕上有太多的圖層占用了。
Instruments
圖上面一部分是第一種方法的數(shù)據(jù),下面一部分是第四種方法的數(shù)據(jù)。
第一種方法的Renderer Utilization 和 Tiler Utilization 基本在90%左右。幀率在20左右。
第四種方法的Renderer Utilization 和 Tiler Utilization 基本在20%左右。幀率接近60。
幀率越接近60滑動(dòng)越順暢。
但是經(jīng)過跟@nerozhao的討論發(fā)現(xiàn)第四種Core Graphics繪制圓角會(huì)有大量的內(nèi)存占用,
而且每次繪制的時(shí)候CUP消耗會(huì)很大。
由于@nerozhao使用了UITableView進(jìn)行測(cè)試,因?yàn)閁ITableView滾動(dòng)的時(shí)候是一直在復(fù)用的,UIImageView會(huì)重復(fù)繪制,所以會(huì)一直消耗CUP,然后你就能看的明顯的卡頓。
@nerozhao在UITableView里圖片的繪制在后臺(tái)線程進(jìn)行繪制,解決了卡頓問題,但是由于是在后臺(tái)線程的異步繪制所以在滾動(dòng)的時(shí)候會(huì)看到圖片先是正方形然后再變成圓形。
而我使用的是UIScrollerView進(jìn)行的測(cè)試,只有第一次繪制的時(shí)候會(huì)占用CUP資源,所以滑動(dòng)的時(shí)候還是挺流暢的,但是內(nèi)存消耗還是很大。如果是主線程繪制的話會(huì)阻塞一點(diǎn)時(shí)間的主線程,而后臺(tái)線程繪制的話內(nèi)存消耗會(huì)更大,特別容易崩潰。
所以第四種方法當(dāng)圖片特別多的時(shí)候很容易R(shí)eceived memory warning導(dǎo)致崩潰

junyixie.github.io/2017/01/20/iOS-%E5%9B%BE%E5%83%8F%E7%BB%98%E5%88%B6/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,836評(píng)論 6 540
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,275評(píng)論 3 428
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,904評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,633評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,368評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,736評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,740評(píng)論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,919評(píng)論 0 289
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,481評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,235評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,427評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,968評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,656評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,055評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,348評(píng)論 1 294
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,160評(píng)論 3 398
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,380評(píng)論 2 379

推薦閱讀更多精彩內(nèi)容

  • 一般我們?cè)趇OS開發(fā)的過程中設(shè)置圓角都是如下這樣設(shè)置的。 所有如果要高性能的設(shè)置圓角就需要找另外的方法了。下面是我...
    齊滇大圣閱讀 15,060評(píng)論 29 98
  • (1)Time Profiler:用來測(cè)量被方法/函數(shù)打斷的CPU使用情況。 (2)Core Animation:...
    錢噓噓閱讀 1,490評(píng)論 2 6
  • _BK_閱讀 313評(píng)論 0 1
  • 時(shí)至今日,來竹溪已經(jīng)半個(gè)月了。也漸漸地習(xí)慣了它們辣辣的飯菜,說著滿口方言的學(xué)生,還有簡(jiǎn)陋的居住條件。 當(dāng)再次去想為...
    秀兒hhh閱讀 450評(píng)論 3 5
  • 在二十世紀(jì),每個(gè)人都認(rèn)為最重要的事情是:證明自己。外向的人憑借他們的高度自信與合群的行為,理所當(dāng)然的成為了香餑餑。...
    獨(dú)不鳴閱讀 2,283評(píng)論 31 41