本篇我們來講一下 阿里勃痴、字節(jié):一套高效的iOS面試題 中的視圖&圖形相關的問題.
視圖&圖像相關
主要問題列表如下:
- AutoLayout的原理,性能如何
- UIView & CALayer的區(qū)別
- 事件響應鏈
- drawrect & layoutsubviews調(diào)用時機
- UI的刷新原理
- 隱式動畫 & 顯示動畫區(qū)別
- 什么是離屏渲染
- imageName&imageWithContentsOfFile區(qū)別
- 多個相同的圖片,會重復加載嗎
- 圖片是什么時候解碼的狭郑,如何優(yōu)化
- 圖片渲染怎么優(yōu)化
- 如果GPU的刷新率超過了iOS屏幕60Hz刷新率是什么現(xiàn)象,怎么解決
1.AutoLayout的原理汇在,性能如何?
AutoLayout的原理
來歷 一般大家都會認為Auto Layout這個東西是蘋果自己搞出來的翰萨,其實不然,早在1997年Alan Borning, Kim Marriott, Peter Stuckey等人就發(fā)布了《Solving Linear Arithmetic Constraints for User Interface Applications》論文(論文地址:http://constraints.cs.washington.edu/solvers/uist97.html)提出了在解決布局問題的Cassowary constraint-solving算法實現(xiàn)糕殉,并且將代碼發(fā)布在他們搭建的Cassowary網(wǎng)站上http://constraints.cs.washington.edu/cassowary/亩鬼。后來更多開發(fā)者用各種語言來寫Cassowary,比如說pybee用python寫的https://github.com/pybee/cassowary阿蝶。自從它發(fā)布以來JavaScript辛孵,.NET,JAVA赡磅,Smalltall和C++都有相應的庫魄缚。2011年蘋果將這個算法運用到了自家的布局引擎中,美其名曰Auto Layout焚廊。
論文下載鏈接比較慢,我下載了一份Cassowary原文放到了我的博客 大家可以自由下載.
AutoLayout的原理就是用Cassowary算法來將布局問題抽象成線性不等式冶匹,并分解成多個位置間的約束
因為多了計算視圖大小frame的過程,所以性能肯定沒有指定Frame坐標要快.
詳細的原理以及高階原理請參考戴銘老師的文章 戴銘老師寫的 深入剖析Auto Layout,分析iOS各版本新增特性
性能如何?
下面是WWDC2018 High Performance Auto Layout中對比的iOS12和iOS11下分別使用自動布局的性能對比現(xiàn)場.
經(jīng)過實驗得出如下圖標結論:
iOS12之前咆瘟,視圖嵌套的數(shù)量對性能的影響是呈指數(shù)級增長的嚼隘,而iOS12優(yōu)化之后對性能的影響是線性增長,對性能消耗不大袒餐。
無論如何優(yōu)化也肯定不如CGRectFrame那樣的設置更加直接,性能更好.
2.UIView & CALayer的區(qū)別
區(qū)別 | UIView | CALayer |
---|---|---|
繼承父類 | UIView:UIResponder:NSObject | CALayer:NSObject |
用途 | 可以處理觸摸事件 | 不處理用戶的交互,不參與響應事件傳遞 |
兩者關系 | 有一個CALayer成員變量 eg: view.layer | 是UIView的成員變量 |
分工 | 處理交互層事件并包裝各種圖形的簡單設置 | 底層渲染圖形,支持動畫 |
3.事件響應鏈
下面這篇文章我已經(jīng)在前幾篇將runloop的時候提了不止一次,前列建議閱讀,快手的同事大部分都以這個理解為標準
4. drawrect & layoutsubviews調(diào)用時機
layoutSubviews:
(相當于layoutSubviews()函數(shù))在以下情況下會被調(diào)用:
- init初始化不會觸發(fā)layoutSubviews飞蛹。
- addSubview會觸發(fā)layoutSubviews谤狡。
- 設置view的Frame會觸發(fā)layoutSubviews (frame發(fā)生變化觸發(fā))。
- 滾動一個UIScrollView會觸發(fā)layoutSubviews卧檐。
- 旋轉(zhuǎn)Screen會觸發(fā)父UIView上的layoutSubviews事件墓懂。
- 改變一個UIView大小的時候也會觸發(fā)父UIView上的layoutSubviews事件。
- 直接調(diào)用setLayoutSubviews霉囚。
drawrect:
(drawrect()函數(shù))在以下情況下會被調(diào)用:
-
drawrect:
是在UIViewController的loadView:
和ViewDidLoad:
方法之后調(diào)用. - 當我們調(diào)用
[UIFont的 sizeToFit]
后,會觸發(fā)系統(tǒng)自動調(diào)用drawRect:
- 當設置UIView的contentMode或者Frame后會立即觸發(fā)觸發(fā)系統(tǒng)調(diào)用
drawRect:
- 直接調(diào)用
setNeedsDisplay
設置標記 或setNeedsDisplayInRect:
的時候會觸發(fā)drawRect:
知識點擴充: 當我們操作drawRect方法的時候?qū)嶋H是在操作內(nèi)存中存放視圖的backingStore區(qū)域,用于后續(xù)圖形的渲染操作,如果不理解可以看下UIView的渲染過程.
5.UI的刷新原理
這個問題我不知道問的是不是iOS離屏渲染過程,我來簡單的回到一下這個吧
iOS 的MainRunloop
是一個60fps 的回調(diào),也就是說16.7ms(毫秒)會繪制一次屏幕在這過程中要完成以下的工作:
- view的緩沖區(qū)創(chuàng)建
- view內(nèi)容的繪制(如果重寫了 drawRect)
- 接收和處理系統(tǒng)的觸摸事件
我們看到的UI圖形實際上是CPU和GPU不斷配合工作的結果.經(jīng)過UIView的渲染過程 后我們的UI會不間斷的接收系統(tǒng)圖給我們的事件.
由于主線程的runloop 一直在回調(diào),我們的UI就得到了刷新的窗口,是渲染還是處理事件都是因為runloop不斷工作的結果.前幾篇我們學過 main線程的runloop默認是啟動的.因為我們響應交互.
不知道我這樣回答是否滿足這個問題的答案.如果回答的不對煩請下方評論區(qū)留言 告知我將持續(xù)改進.
6.隱式動畫 & 顯示動畫區(qū)別
隱式動畫一直存在 如需關閉需設置
顯式動畫是不存在捕仔,如需顯式 要開啟
只需要觀察動畫執(zhí)行完成的結果 比如: 一個簡單UIView的frame移動 如果從A點移動到B點 移動完成 回到原始位置就是隱式動畫
Core Animation 是顯式動畫.因為它既可以直接對其layer屬性做動畫,也可以覆蓋默認的圖層行為.
7.imageName&imageWithContentsOfFile區(qū)別
區(qū)別 | UIView | imageWithContentsOfFile |
---|---|---|
不同點 | 會圖片緩存到內(nèi)存中 | 無緩存 |
8.什么是離屏渲染
9.多個相同的圖片盈罐,會重復加載嗎
不會,GPU有 像素點緩存的mask.
10.圖片是什么時候解碼的榜跌,如何優(yōu)化
是加載到內(nèi)存中,從UIImge->CGImage->CGImageSourceCreateWithData(data) 創(chuàng)建ImageSource變成bitmap位圖,這些工作都是CoreAnimation在圖片被加載到內(nèi)存中存在在backingStore里,送給GPU流水線處理之前被解碼.
如何優(yōu)化
自己手動操作圖片的編碼API
CGImageSource開頭的哪些,根據(jù)合理利用時機和操作系統(tǒng)資源調(diào)整出一套緩存小加載快的庫.
參考PINRemoteImage或者YYWebImage開源
11.圖片渲染怎么優(yōu)化
可以從陰影,圓角入手.幀率,電量,圖片的鋸齒等等.
12.如果GPU的刷新率超過了iOS屏幕60Hz刷新率是什么現(xiàn)象,怎么解決
現(xiàn)象是 圖形清晰,場景逼真,但是一般arm芯片的GPU 刷新超過60Hz一定會超級費電,手機發(fā)熱導致降頻.FPS降低,因為低能耗電量不足,無法支持GPU高刷新率
解決辦法只能用xcode自帶工具檢測,看渲染過程哪里可以優(yōu)化.
總結
簡單回答了一些圖形相關的問題,大部分都是iOS離屏渲染,這個地方大家要認真學習.很多資料看起來比較耗時.
收錄:原文地址