本文簡單介紹了iOS中離屏渲染的相關內容呢。算法
要了解離屏渲染,咱們先簡單瞭解一下非離屏渲染的邏輯緩存
非離屏渲染也就是正常的渲染流程,簡要流程如圖: bash
APP將要渲染的信息提交給CPU,CPU經過必定的處理後提交給GPU。GPU不停的將內容渲染完成放到幀緩衝區中(FrameBuffer)。最後顯示到屏幕上。離屏渲染簡要流程如圖: 佈局
與普通流程不一樣的是,GPU把渲染好的的內容存放到離屏渲染緩衝區中,在離屏渲染緩衝區(OffscreenBuffer)中進一步作一些處理後,再提交到幀緩衝區(FrameBuffer)中。模擬器->Debug->Color Off-screen Rendered 性能
開啓後在模擬器界面中能看到使用離屏渲染的View了 圖片中的例子是一個button,設置了一個背景色和背景圖,對layer層設置cornerRadius和masksToBounds。masksToBounds=YES,若是不設置是看不到效果的。下面會具體說明緣由。ui
使用離屏渲染大體有一下兩種狀況:spa
通常都是系統去觸發,例如對layer層相關處理:包括圓角、陰影、mask等等。iOS系統扁平化後出現的高斯模糊也是利用離屏渲染方式。code
設置圓角爲何會觸發離屏渲染呢?這個要從layer的結構提及。 layer結構中包含3部分:orm
設置圓角代碼,這個你們應該都知道:cdn
view.layer.cornerRadius = 2
複製代碼
咱們先看看官方文檔中cornerRadius相關說明:
Discussion中的說明: 設置cornerRadius超過0.0,不會影響contents,可是會影響background color和border。若是設置了masksToBounds會對content進行裁剪。 因此說出發離屏渲染的主要緣由:masksToBounds=YES;
複製代碼
這就是上面模擬器開啓離屏渲染模式中說明的爲何要設置masksToBounds的緣由。masksToBounds須要對layer上的全部內容進行裁剪,過程當中須要對中間值進行保存。因此進行了離屏渲染操做。
注意: 若是說layer圖層比較簡單,也是不會觸發離屏渲染的。例如:UIImageView設置cornerRadius和masksToBounds是不會觸發離屏渲染的,若是再對UIImageView設置背景色,則會觸發。
self.view.backgroundColor = [UIColor grayColor];
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"1"]];
imageView.frame = CGRectMake(100, 100, 100, 100);
imageView.layer.cornerRadius = 30;
imageView.layer.masksToBounds = YES;
[self.view addSubview:imageView];
UIImageView *imageView2 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"1"]];
imageView2.backgroundColor = UIColor.redColor;
imageView2.frame = CGRectMake(100, 250, 100, 100);
imageView2.layer.cornerRadius = 30;
imageView2.layer.masksToBounds = YES;
[self.view addSubview:imageView2];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setBackgroundImage:[UIImage imageNamed:@"1"] forState:UIControlStateNormal];
btn.layer.cornerRadius = 30;
btn.layer.masksToBounds = YES;
btn.frame = CGRectMake(100, 400, 100, 100);
[self.view addSubview:btn];
複製代碼
代碼中有三個控件,前兩個是UIImageView,最後一個是UIButton。
是一種主動行爲,是爲了提升複用的效率。一般是設置layer的shouldRasterize屬性來實現。
shouldRasterize官方文檔
開啓後,會將layer做爲位圖保存下來,下次直接與其餘內容進行混合。這個保存的位置就是OffscreenBuffer中。這樣下次須要再次渲染的時候,就能夠直接拿來使用了。shouldRasterize使用建議:
圖層的疊加繪製大體遵循「畫家算法」,也就是由遠到近的方式將圖層繪製到屏幕上,繪製近距離圖層會有覆蓋遠圖層的邏輯。
普通渲染方式,繪製完一層圖層後,直接捨棄掉。緊接着繪製稍近的圖層。以此類推:
而咱們進行離屏渲染方式(圓角、剪裁等操做)時,每層圖層繪製完不會立刻刪除,而是先保存在離屏緩存區中,等圖層繪製完成後,再依次進行特殊處理(圓角、剪裁等操做)。 注意:一般會觸發離屏渲染,除了圓角、剪裁外,還有設置了透明度+組透明(layer.allowsGroupOpacity+layer.opacity),陰影屬性(shadowOffset 等)都會產生相似的效果,由於組透明度、陰影都是和裁剪相似的,會做用與 layer 以及其全部 sublayer 上,這就致使必然會引發離屏渲染。爲了不設置圓角時引發的離屏渲染操做,能夠用一下方案代替直接設置圓角的操做