在性能優化中一個最具參考價值的屬性是 FPS:Frames Per Second,其實就是屏幕刷新率,蘋果的 iphone 推薦的刷新率是 60Hz,也就是說 GPU 每秒鐘刷新屏幕 60次,這每刷新一次就是一幀 frame,FPS 也就是每秒鐘刷新多少幀畫面。靜止不變的頁面 FPS 值是 0,這個值是沒有參考意義的,只有當頁面在執行動畫或者滑動的時候,FPS 值才具有參考價值,FPS 值的大小體現了頁面的流暢程度高低,當低于 45 的時候卡頓會比較明顯。
圖層混合:
每一個 layer 是一個紋理,所有的紋理都以某種方式堆疊在彼此的頂部。對于屏幕上的每一個像素,GPU 需 要算出怎么混合這些紋理來得到像素 RGB 的值。
當 Sa=0.5 時,RGB 值為(0.5,0,0),可以看出,當兩個不是完全不透明的 CALayer 覆蓋在一起時,GPU 大量做 這種復合操作,隨著這中操作的越多,GPU 越忙碌,性能肯定會受到影響。
公式:
R=S+D(1–Sa)
結果的顏色是源色彩(頂端紋理)+目標顏色(低一層的紋理)(1-源顏色的透明度)。
當 Sa=1 時,R=S,GPU 將不會做任何合成,而是簡單從這個層拷貝,不需要考慮它下方的任何東西(因為都 被它遮擋住了),這節省了 GPU 相當大的工作量。
一、入門級
1、用 ARC 管理內存
2、在正確的地方使用 reuseIdentifier
3、盡量把 views 設置成透明
4、避免過于龐大的 xib
5、不要阻塞主線程
6、在 imageViews 調整圖片大小。如果要在 UIImageView 中顯示一個來自 bundle 的圖片,你因該保證圖片的大小和 UIImageView 的大小相同。在運行中縮放圖片是很耗費資源的,特別是 UIImageView 嵌套在 UIScrollView 中的情況下。如果圖片是從遠端服務加載的你不能控制圖片大小,你可以在下載完成后,最好是用 background thread,縮放一次,然后在 UIImageView 中使用縮放后的圖片。
7、選擇正確的 Collection
- Arrays:有序的一組值。使用 index 來 lookup 很快,使用 value 來 lookup 很慢,插入和刪除很慢
- Dictionaries:存儲鍵值對。用鍵來查找比較快。
- Sets:無序的一組值。用值來查找很快,插入和刪除很快。
8、打開 gzip壓縮。app 可能大量依賴于服務器資源,問題是我們的對象是移動設備,你不能指望網絡狀況有多好。減小文檔的一個方式就是在服務器端和你的 app 中打開 gzip。這對于文字這種能有更高壓縮率的數據來說會有更顯著的效用。
二、中級
1、重用和延遲加載(lazy load)views
- 更多的 view 意味著更多的渲染,也就是更多的 CPU 和內存消耗,對于那種嵌套了很多 view 在 UIScrollView 里邊的 app 更是如此。
- 這里我們用到的技巧就是模仿 UItableView 和 UICollectionView 的操作:不要一次創建了所有的 subview,而是當需要時才創建,當他們完成使命時,把它們放進一個可重用的隊列中。這樣的話你就只需要在滾動發生時創建你的 views,避免了不必要的內存分配。
2、Cache,Cache,還是 Cache!
- 一個極好的原則就是,緩存所需要的,也就是說那些不大可能發生改變但是需要經常讀取的東西。
- 我們能緩存些什么呢?一些選項是,服務器的響應、圖片、甚至是計算結果、UITableview 的行高。
- NSCache 和 NSDictionary 類似,不同的是系統回收內存時它會自動刪除它的的內容。
3、權衡渲染方法,性能能還是要 bundle 保持合適的大小。
4、處理內存警告,移除對緩存、圖片object、和其他一些可以 重創建的 objects 的 strong references。
5、重用大開銷對象
6、一些 objects 的初始化很慢,比如 NSDateFormater 和 NSCaledar。然而你又不可避免的需要使用它們,比如從 JSON 或者 XML 中解析數據。想要避免使用這個對象的瓶頸你就需要重用他們,可以通過添加屬性到你的 Class 里或者創建靜態變量來實現。
7、避免反復處理數據,在服務器端和客服端使用相同的數據結構很重要。
8、選擇正確的數據格式,解析 JSON 會比 XML更快一些,JSON 通常也更小更便與傳輸。從 iOS5 起有了官方內建的 JSON deserialization就更加方便使用了。但是 XML 也有 XML 的好處,比如使用 SAX 來 解析 XML 就像解析本地文件一樣,你不需要像解析 JSON 一樣要等到整個文檔下載完成才開始解析,當你處理很大的數據的時候就會很大的減低內存消耗和增加性能。
9、正確設定背景圖片
- 全屏背景圖,在 view 中添加一個 UIIMageView 作為一個子View。
- 只是某個小 View 的背景圖,你就需要用 UIColor 的 colorWithPatternImage 來做了,它會更快的渲染也不會花費很多的內存。
10、減少使用 Web 特性,想要更高的性能你就需要改一下你的 HTML 了。第一件要做的事就是盡可能的移除不必要的 JavaScript,避免使用過大的框架。能只用原生 js 就更好了。盡可能異步加載例如用戶行為統計 script 這種不影響頁面表達的 JavaScript。注意你使用的圖片,保證圖片的大小符合你的使用。
11、Shadow Path,CoreAnimation 不得不先在后臺得出你的圖形并加好陰影才渲染,這開銷是很大的。使用 shadowpath 的話就可以避免了這個問題。使用 shadowpath 的話 iOS 就不必每次都去計算如何渲染,它使用一個預先計算好的路徑。但問題是自己計算 path 的話,可能在某些 view 中比較困難,且每當 view 的 frame 發生變化時你都要去 update shadow path。
12、優化 TableView
- 正確使用 reuseidentifier 來重用 cells
- 盡量使所有的 view opaque,包括 cell 自身。
- 避免漸變、圖片縮放、后臺渲染
- 緩存行高
- 如果 cell 顯示的內容來自 web,使用異步加載,緩存請求結果
- 使用 shadow path 來畫陰影
- 盡量不使用 cellForRowAtIndexPath,如果你需要用到它,只用一次然后緩存結果
- 減少 subviews 的數量
- 使用正確的數據結構來存儲數據
- 使用 rowHeight、sectionFooterHeight 和 sectionHeaderHeight 來設定固定的高,不要請求 delegate
13、選擇正確的數據存儲選項
- NSUserDefaults 的問題是什么?雖然它很 nice 也很便捷,但它只適用于小數據,比如一些簡單的布爾型的設置選項,再大點你就要考慮其他方式了。
- XML 這種結構化文檔呢?總體來說,你需要讀取整個文件到內存里來解析,這樣是很不經濟的,而且使用 SAX 是一個很麻煩的事情。
- NSCoding?不幸的是,它也需要讀寫文件,所以也有以上問題。
- 在這種應用場景下,使用 SQLite 或者 Core Data 比較好。使用這些技術你用特定的查詢語句就能只加載你需要的對象。
- 在性能層面來講,SQLite 和 Core Data 很相似,他們的不同在于具體使用方法
- Core Data 代表一個對象的 graph model,但 SQLite 就是一個 DBMS
- Apple 在一般情況下建議使用 core data,但是如果有理由不去使用它,那就去使用更加底層的 SQLite 吧。
- 如果你使用 SQLite,你可以使用 FMDB 來簡化 SQLite 的操作,這樣你就可以不用花很多精力來了解 SQLite 的 C API 了。
三、高級
1、加速啟動時間。
快速打開 app 是很重要的,特別是用戶第一次打開它時,對于 app 來說,第一印象太太太重要了。你能做的就是使他盡可能做更多異步任務,比如加載遠端或者數據庫數據,解析數據。避免過于龐大的 xib,因為它們是在主線程上加載的。所以盡量使用沒有這個問題的 storyboards 吧,一定要不把設備從 Xcode 斷開來測試它的啟動速度。
2、使用 AutoRelease Pool。
NSAutoReleasePool 負責釋放 block 中 autorelease objects。一般情況下它會自動被 UIKit 調用。但是有些情況你需要手動去創建它們,假如你創建很多臨時對象,你會發現內存一直在減少直到這些對象被 autorelease 的時候。這是因為 UIKit 在用光了 autorelease pool 的時候 memory 才會釋放。但是你可以在自己的 @autoreleasepool 中創建臨時對象來避免這個行為。
3、選擇是否緩存圖片。
常見的從 bundle 中加載圖片的方式有兩種,一個是用 imageNamed,二是用 imageWithContentsOfFile,第一種比較常見一點。
4、避免日期格式轉換。
如果你要用 NSDateFormatter 來處理很多日期格式,因該小心以待。就像先前提到的,任何時候重用 NSDateFormatter 都是一個好的實踐,如果你可以控制你所處理的日期格式,盡量選擇 Unix 時間戳。你可以方便地從時間戳轉換到 NSDate:
- (NSDate *)dateFormUnixTimestamp:(NSTimeInterval)timestamp {
return [NSDate dateWithTimeIntervalSince1970: timestamp];
}
這樣會比用 C 來解析日期字符串還快!需要注意到的是很多 web API 會以微秒的形式來返回時間戳,因為這種格式在 JavaScript 中更方便使用,記得在使用 dateFromUnixTimestamp之前除以 1000 就好了。
5、平時你是如何對代碼進行性能優化的?
- 利用性能分析工具檢測,包括靜態 Analyze 工具,以及運行時 Profile 工具,可以通過 Xcode 工具欄中 Product ->Profile 可以啟動。
- 比如測試應用的啟動運行時間,當點擊 Time Profiler 應用程序開始運行后,就能獲取到整個應用程序運行消耗時間和百分比。為了保證數據分析在統一使用場景真實需要注意一定要使用真機,因為此時模擬器是運行在 Mac 上,而 Mac 上的 CPU 往往比 iOS 設備要快。
- 為了防止一個應用占用過多的系統資源,開發 iOS 的蘋果工程師們設計了一個"看門狗"的機制。在不 同的場景下,“看門狗”會監測應用的性能。如果超出了該場景所規定的運行時間,“看門狗”就會強制 終結這個應用的進程。開發者們在 crashlog 里面,會看到諸如 0x8badf00d 這樣的錯誤代碼。
6、UIImage 加載圖片性能問題
- imageNamed 初始化
- imageWithContentsOfFile 初始化
- imageNamed 默認加載加載圖片成功后會在內存中緩存這個圖片,這個方法用一個指定的名字在系統緩存中查找并返回一個圖片對象。如果緩存中沒有找到指定的圖片對象,則從指定位置加載對象然后緩存對象,并返回這個圖片對象。
- imageWithContentsOfFile 則僅加載圖片,不緩存。
- 加載一張大圖并且使用一次,用 imageWithContensOfFile 是最好,這樣 CPU 不需要做緩存節約時間。
- 使用場景需要編程時,應根據實際應用場景加以區分,但使用元素較多問題會有所凸顯。
- 不要在 viewWillAppear 中做費時的操作:viewWillAppear: 在 view 顯示之前被調用,出于效率考慮,方法中不要處理復雜費時操作;在該方法設置 view 的顯示屬性之類的簡單事情,比如背景色, 字體等。否則,會明顯感覺到 view 有卡頓或者延遲。
- 在正確的地方使用 reuseIdentifier:tableview 用 tableView:cellForRowAtIndexPath:為 rows 分配 cells 的時候,它的數據應該重用自 UITableViewCell。
- 盡量把 views 設置為透明:如果你有透明的 Views 你應該設置它們的 opaque 屬性為 YES。系統用 一個最優的方式渲染這些 views。這個簡單的屬性在 IB 或者代碼里都可以設定。
- 避免過于龐大的 XIB:盡量簡單的為每個 Controller 配置一個單獨的 XIB,盡可能把一個 View Controller 的 view 層次結構分散到單獨的 XIB 中去, 當你加載一個引用了圖片或者聲音資源的 nib 時, nib 加載代碼會把圖片和聲音文件寫進內存。
- 不要阻塞主線程:永遠不要使主線程承擔過多。因為 UIKit 在主線程上做所有工作,渲染,管理 觸摸反應,回應輸入等都需要在它上面完成,大部分阻礙主進程的情形是你的 app 在做一些牽涉到讀寫 外部資源的 I/O 操作,比如存儲或者網絡。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 選擇一個子線程來執行耗時操作
dispatch_async(dispatch_get_main(), ^{
// 返回主線程更新UI
});
});
- 在 ImageViews 中調整圖片大小
如果要在 UIImageView 中顯示一個來自 bundle 的圖片,你應保證圖片的大小和 UIImageView 的大小相 同。在運行中縮放圖片是很耗費資源的.
7、講講你用 Instrument 優化動畫性能的經歷吧(別問我什么是 Instrument)
Apple的 instrument 為開發者提供了各種 template 去優化 app 性能和定位問題很多公司都在趕 feature,并沒有充足的時間來做優化r導致不少開發者對 instrument 不怎么熟悉,舊這里面其實涵蓋了非常完整的計算機基礎理論知識體系,memory,disk,network, thread,cpu,epu等等,順薛摸瓜去學習,是筆巨大的知識財富。動畫性能只是其中一個 template,重點還是理解上面向題當中 CPU GPU 如何配合工作的知識。
8、facebook 啟動時間優化
- 瘦身請求依賴
- UDP 啟動請求先行緩存
- 隊列串行化處理啟動響應
四、光柵化
光柵化是將幾何數據經過一系列變換后轉換成像素,從而呈現在顯示設備上的過程,光柵化的本質是坐標變化、幾何離散化。
我們使用 UITableView 和 UICollectionView 時經常會遇到各個 cell 的樣式是一樣的,這時候我們可以使用這個屬性提高性能。
cell.layer.shouldRasterize = YES;
cell.layer.RasterizationScale = [UIScreen mainScreen].scale;
五、日常如何檢查內存泄露?
目前我知道的方式有以下幾種:
- Memory leaks
- AIloctions
- Analyse
- Debug Memory Graph
- MLeaksFinder
泄露的內存主要有以下兩種:
- Lak Memory 這種是忘了 Release 操作所泄露的內存
- Abandon Memory 這種是循環引用,無法釋放掉的內存
上面所說的五種方式,其實前四種比較麻煩,需要不斷地調試運行,第五種是騰訊閱讀團隊出品,效果好一些。
六、如何高性能的畫一個圓角?
視圖和圓角的大小對幀率沒有什么影響,數量才是傷害的核心輸出。
lable.layer.cornerRadius = 5;
lable.layer.masksToBounds = true;
首先上面的方式是不可取的,會觸發離屏渲染。
- 如果能夠只用 cornerRadius 解決問題,就不用優化。
- 如果必須設置 masksToBounds,可以參考圓角視圖的數量,如果數量較少(一頁只有幾個)也可以考慮不用優化。
- UIImageView 的圓角通過直接截取圖片實現,其他視圖的圓角可以通過 Core Graphics 畫出圓角矩形實現。
七、如何提升 tableview 的流暢度?
本質上是降低 CPU、GPU 的工作,從這兩個大的方面去提升性能。
- CPU:對象的創建和銷毀、對象屬性的調整、布局計算、文本的計算和排版、圖片的格式轉換和解碼、圖像的繪制
- GPU:紋理的渲染
卡頓優化在 CPU 層面
- 盡量用輕量級的對象,比如用不到事件處理的地方,可以考慮用 CALayer 取代 UIView
- 不要頻繁的調用 UIView 的相關屬性,比如 frame,bounds,transform 等屬性,盡量減少不必要的修改
- 盡量提前計算好布局,在有需要時一次性調整到對應的屬性,不要多次修改屬性
- Autolayout 會比直接使用 Frame 消耗更多的 CPU 資源
- 圖片的 size 最好剛好跟 UIImageView 的 size 保持一致
- 控制一下線程的最大并發數量
- 盡量把耗時的操作放到子線程
- 文本處理(尺寸計算、繪制)
- 圖片處理(解碼、繪制)
卡頓優化在 CPU 層面
- 盡可能避免短時間內大量圖片的顯示,盡可能將多張圖片合成一張顯示
- GPU 能夠處理的最大紋理尺寸是 4096x4096,一旦超過這個尺寸,就會占用 CPU 資源進行處理,所以紋理盡量不要超過這個尺寸
- 盡量減少視圖數量和層次
- 減少透明的視圖(alpha<1),不透明的就設置 opaque 為 YES,盡量避免出現離屏渲染
1.預排版,提前計算
- 在接收到服務器端返回的數據后,盡量將 coreText 排版的結果、單個控件的高度、cell 整體的高度提前計算好,將其存儲在模型的屬性中。需要使用時,直接從模型往外取,避免了計算的過程。
- 盡量少用 UILabel,可以使用 CALayer。避免使用 AutoLayout 的自動布局技術,采用純代碼的方式。
2.預渲染,提前繪制
- 例如圓形的圖標可以在接收網絡數據返回時,在后臺線程進行處理,直接存儲在模型數據里,回到主線程后直接調用就好了。
- 避免使用 CALayer 的 Border、corner、shadow、mask 的屬性,這些都會觸發離屏渲染。
3.異步繪制
4.全局并發線程
5.高效的圖片異步加載
八、如何優化 APP 的電量?
程序的耗電主要在以下四個方面:
- CPU 處理
- 定位
- 網絡
- 圖像
優化的途徑主要有以下幾個方面:
- 盡量降低 CPU 和 GPU 的功耗。
- 盡量少用定時器
- 優化 I/O 操作
- 不要頻繁地寫入小數據,而是積攢到一定數量再寫入
- 讀寫大量的數據可以可以使用Dispatch_io,GCD 內部已經做了優化。
- 數據量較大時,建議使用數據庫
- 網絡方面的優化
- 減少壓縮網絡數據 (XML->JSON->ProtoBuf),如果可能建議使用 ProtoBuf
- 如果請求的返回數據相同,可以使用 NSCache 進行緩存
- 使用斷點續傳,避免因網絡失敗后要重新下載
- 網絡不可用的時候,不嘗試進行網絡請求
- 長時間的網絡請求,要提供可以取消的操作
- 采取批量傳輸。下載視頻流的時候,盡量一大塊一大塊的進行下載,廣告可以一次下載多個
- 定位層面的優化
- 如果只是需要快速確定用戶位置,最好用 CLLocationManager 的 requestLocation 方法。 定位完成后,會自動讓定位硬件斷電
- 如果不是導航應用,盡量不要實時更新位置,定位完畢就關掉定位服務
- 盡量降低定位精度,比如盡量不要使用精度最高的 kCLLocationAccuracyBest
- 需要后臺定位時,盡量設置 pausesLocationUpdatesAutomatically 為 YES,如果用戶不太可能移動的時候系統會自動暫停位置更新
- 盡量不要使用 startMonitoringSignificantLocationChanges , 優先考慮 startMonitoringForRegion:
- 硬件檢測優化
- 用戶移動、搖晃、傾斜設備時,會產生動作(motion)事件,這些事件由加速度計、陀螺儀、 磁力計等硬件檢測。在不需要檢測的場合,應該及時關閉這些硬件
九、如何有效降低 APP 包的大小?
降低包大小需要從兩方面入手
可執行文件
- 編譯器優化
- StripLinkedProduct、MakeStringsRead-Only、SymbolsHiddenbyDefault 設置為 YES
- 去掉異常支持,EnableC++Exceptions、EnableObjective-CExceptions 設置為 NO, OtherCFlags 添加 -fno-exceptions
資源
資源包括 圖片、音頻、視頻 等
- 優化的方式可以對資源進行無損的壓縮
- 去除沒有用到的資源
十、什么是 離屏渲染?什么情況下會觸發?該如何應對?
離屏渲染就是在當前屏幕緩沖區以外,新開辟一個緩沖區進行操作。
觸發離屏渲染的場景有以下:
- 圓角(masksTobounds 并用才會觸發)
- 圖層蒙版
- 陰影
- 光柵化
為什么要避免離屏渲染?
CPU GPU 在繪制渲染視圖時做了大量的工作。離屏渲染發生在 GPU 層面上,會創建新的渲染緩沖區,會觸發 OpenGL 的多通道渲染管線,圖形上下文的切換會造成額外的開銷,增加 GPU 工作量。如果 CPU GPU 累計耗時 16.67 毫秒還沒有完成,就會造成卡頓掉幀。
圓角屬性、蒙層遮罩 都會觸發離屏渲染。指定了以上屬性,標記了它在新的圖形上下文中,在未愈合之前,不可以用于顯示的時候就觸發了離屏渲染。
- 在 OpenGL 中,GPU 有 2 種渲染方式
- On-ScreenRendering:當前屏幕渲染,在當前用于顯示的屏幕緩沖區進行渲染操作
- Off-ScreenRendering:離屏渲染,在當前屏幕緩沖區以外新開辟一個緩沖區進行渲染操作
- 離屏渲染消耗性能的原因
- 需要創建新的緩沖區
- 離屏渲染的整個過程,需要多次切換上下文環境,先是從當前屏幕(On-Screen)切換到離屏 (Off-Screen);等到離屏渲染結束以后,將離屏緩沖區的渲染結果顯示到屏幕上,又需要將上下文環境從離屏切換到當前屏幕
- 哪些操作會觸發離屏渲染?
- 光柵化,layer.shouldRasterize=YES
- 遮罩,layer.mask
- 圓角,同時設置 layer.masksToBounds=YES、layer.cornerRadius 大于 0
- 考慮通過 CoreGraphics 繪制裁剪圓角,或者叫美工提供圓角圖片
- 陰影,layer.shadowXXX,如果設置了 layer.shadowPath 就不會產生離屏渲染
十一、如何檢測離屏渲染?
1、模擬器 debug-選中 colorOffscreen-Renderd 離屏渲染的圖層高亮成黃 可能存在性能問題
2、真機 Instrument-選中 CoreAnimation-勾選 ColorOffscreen-RenderedYellow
離屏渲染的觸發方式
設置了以下屬性時,都會觸發離屏繪制:
1、layer.shouldRasterize(光柵化)
光柵化概念:將圖轉化為一個個柵格組成的圖象。
光柵化特點:每個元素對應幀緩沖區中的一像素。
2、masks(遮罩)
3、shadows(陰影)
4、edgeantialiasing(抗鋸齒)
5、groupopacity(不透明)
6、復雜形狀設置圓角等
7、漸變
8、drawRect
- 例如我們日程經常打交道的 TableViewCell,因為 TableViewCell 的重繪是很頻繁的(因為 Cell 的復用),如果 Cell 的內容不斷變化,則 Cell 需要不斷重繪,如果此時設置了 cell.layer 可光柵化。則會造成大量的離屏渲染, 降低圖形性能。
- 如果將不在 GPU 的當前屏幕緩沖區中進行的渲染都稱為離屏渲染,那么就還有另一種特殊的“離屏渲染”方 式:CPU 渲染。
- 如果我們重寫了 drawRect 方法,并且使用任何 CoreGraphics 的技術進行了繪制操作,就涉 及到了 CPU 渲染。整個渲染過程由 CPU 在 App 內同步地完成,渲染得到的 bitmap 最后再交由 GPU 用于顯示。
- 現在擺在我們面前得有三個選擇:當前屏幕渲染、離屏渲染、CPU 渲染,該用哪個呢?這需要根據具體的 使用場景來決定
盡量使用當前屏幕渲染
鑒于離屏渲染、CPU 渲染可能帶來的性能問題,一般情況下,我們要盡量使用當前屏幕渲染。
離屏渲染 VS CPU 渲染
由于 GPU 的浮點運算能力比 CPU 強,CPU 渲染的效率可能不如離屏渲染;但如果僅僅是實現一個簡單的效 果,直接使用 CPU 渲染的效率又可能比離屏渲染好,畢竟離屏渲染要涉及到緩沖區創建和上下文切換等耗時操作UIButton 的 masksToBounds=YES 又設置 setImage、setBackgroundImage、
[button setBackgroundColor:[UIColorcolorWithPatternImage:[UIImageimageNamed:@"btn_selected"]]];
下發生離屏渲染,但是[button setBackgroundColor:[UIColor redColor]];
是不會出現離屏渲染的
關于 UIImageView,現在測試發現(現版本:iOS10),在性能的范圍之內,給 UIImageView 設置圓角是不會觸發離 屏渲染的,但是同時給 UIImageView 設置背景色則肯定會觸發.觸發離屏渲染跟 png.jpg 格式并無關聯
日常我們使用 layer 的兩個屬性,實現圓角
imageView.layer.cornerRaidus = CGFloat(10);
imageView.layer.masksToBounds = YES;
這樣處理的渲染機制是 GPU 在當前屏幕緩沖區外新開辟一個渲染緩沖區進行工作,也就是離屏渲染,這會 給我們帶來額外的性能損耗。如果這樣的圓角操作達到一定數量,會觸發緩沖區的頻繁合并和上下文的的 頻繁切換,性能的代價會宏觀地表現在用戶體驗上——掉幀。
十二、怎么檢測圖層混合?
1、模擬器 debug- 選中 colorblendedlayers 紅色區域表示圖層發生了混合
2、Instrument-選中 CoreAnimation-勾選 ColorBlendedLayers
避免圖層混合:
1、確保控件的 opaque 屬性設置為 true,確保 backgroundColor 和父視圖顏色一致且不透明
2、如無特殊需要,不要設置低于 1 的 alpha 值
3、確保 UIImage 沒有 alpha 通道
UILabel 圖層混合解決方法:
- iOS8 以后設置背景色為非透明色并且設置 label.layer.masksToBounds=YES 讓 label 只會渲染她的實際 size 區 域,就能解決 UILabel 的圖層混合問題
- iOS8 之前只要設置背景色為非透明的就行
- 為什么設置了背景色但是在 iOS8 上仍然出現了圖層混合呢?
UILabel 在 iOS8 前后的變化,在 iOS8 以前,UILabel 使用的是 CALayer 作為底圖層,而在 iOS8 開始,UILabel 的底圖層變成了_UILabelLayer,繪制文本也有所改變。在背景色的四周多了一圈透明的邊,而這一圈透明 的邊明顯超出了圖層的矩形區域,設置圖層的 masksToBounds 為 YES 時,圖層將會沿著 Bounds 進行裁剪圖 層混合問題解決了