demo下載ios
通常咱們在iOS開發的過程當中設置圓角都是以下這樣設置的。
git
avatarImageView.clipsToBounds = YES;
[avatarImageView.layer setCornerRadius:50];
這樣設置會觸發離屏渲染,比較消耗性能。好比當一個頁面上有十幾頭像這樣設置了圓角
會明顯感受到卡頓。
注意:png圖片UIImageView處理圓角是不會產生離屏渲染的。(ios9.0以後不會離屏渲染,ios9.0以前仍是會離屏渲染)。
全部若是要高性能的設置圓角就須要找另外的方法了。下面是我找到的一些方法並寫了一個例子。
設置圓角的方法
github
(1)直接使用setCornerRadius緩存
這種就是最經常使用的,也是最耗性能的。(2) setCornerRadius設置圓角以後,shouldRasterize=YES光柵化
avatarImageView.clipsToBounds = YES;
[avatarImageView.layer setCornerRadius:50];
avatarImageView.layer.shouldRasterize = YES;
avatarImageViewUrl.layer.rasterizationScale=[UIScreen mainScreen].scale; //UIImageView不加這句會產生一點模糊
shouldRasterize=YES設置光柵化,可使離屏渲染的結果緩存到內存中存爲位圖,
使用的時候直接使用緩存,節省了一直離屏渲染損耗的性能。
可是若是layer及sublayers經常改變的話,它就會一直不停的渲染及刪除緩存從新
建立緩存,因此這種狀況下建議不要使用光柵化,這樣也是比較損耗性能的。
(3)
直接覆蓋一張中間爲圓形透明的圖片(推薦使用)
這種方法就是多加了一張透明的圖片,GPU計算多層的混合渲染blending也是會消耗 一點性能的,但比第一種方法仍是好上不少的。(4) UIImage drawInRect繪製圓角
這種方式GPU損耗低內存佔用大,並且UIButton上不知道怎麼繪製,能夠用
UIimageView添加個點擊手勢當作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回調裏,在主線程異步繪製。
也能夠封裝到UIImageView裏,寫了個DSRoundImageView。後臺線程異步繪製,不會阻塞主線程。
問題:這種方法圖片不少的話CUP消耗會高,內存佔用也會暴增,並且後臺線程繪製會比在主線程繪製佔用更多的內存,不知道怎麼解決?求大神指教!
(5)SDWebImage處理圖片時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庫裏處理image的時候使用類別方法繪製圓角並緩存。性能
使用Instruments的Core Animation查看性能測試
Color Offscreen-Rendered Yellow
開啓後會把那些須要離屏渲染的圖層高亮成黃色,這就意味着黃色圖層可能存在性能問題。ui
Color Hits Green and Misses Red
若是shouldRasterize被設置成YES,對應的渲染結果會被緩存,若是圖層是綠色,就表示這些緩存被複用;若是是紅色就表示緩存會被重複建立,這就表示該處存在性能問題了。spa
用Instruments測試線程
第(1)種方法,UIImageView和UIButton都高亮爲黃色。