前言
本篇我們來講一下 【iOS面試題的視圖&圖形】相關(guān)的問題.
視圖&圖像相關(guān)
主要問題列表如下:
- AutoLayout的原理,性能如何
- UIView & CALayer的區(qū)別
- 事件響應(yīng)鏈
- drawrect & layoutsubviews調(diào)用時(shí)機(jī)
- UI的刷新原理
- 隱式動(dòng)畫 & 顯示動(dòng)畫區(qū)別
- 什么是離屏渲染
- imageName&imageWithContentsOfFile區(qū)別
- 多個(gè)相同的圖片,會(huì)重復(fù)加載嗎
- 圖片是什么時(shí)候解碼的,如何優(yōu)化
- 圖片渲染怎么優(yōu)化
- 如果GPU的刷新率超過了iOS屏幕60Hz刷新率是什么現(xiàn)象,怎么解決
1.AutoLayout的原理,性能如何?
AutoLayout的原理
來歷 一般大家都會(huì)認(rèn)為Auto Layout這個(gè)東西是蘋果自己搞出來的,其實(shí)不然,早在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算法實(shí)現(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++都有相應(yīng)的庫。2011年蘋果將這個(gè)算法運(yùn)用到了自家的布局引擎中,美其名曰Auto Layout。
論文下載鏈接比較慢,我下載了一份Cassowary原文放到了我的博客 大家可以自由下載.
AutoLayout的原理就是用Cassowary算法來將布局問題抽象成線性不等式,并分解成多個(gè)位置間的約束
因?yàn)槎嗔擞?jì)算視圖大小frame的過程,所以性能肯定沒有指定Frame坐標(biāo)要快.
詳細(xì)的原理以及高階原理請參考戴銘老師的文章 戴銘老師寫的 深入剖析Auto Layout,分析iOS各版本新增特性
性能如何?
下面是WWDC2018 High Performance Auto Layout中對(duì)比的iOS12和iOS11下分別使用自動(dòng)布局的性能對(duì)比現(xiàn)場.
經(jīng)過實(shí)驗(yàn)得出如下圖標(biāo)結(jié)論:
iOS12之前,視圖嵌套的數(shù)量對(duì)性能的影響是呈指數(shù)級(jí)增長的,而iOS12優(yōu)化之后對(duì)性能的影響是線性增長,對(duì)性能消耗不大。
無論如何優(yōu)化也肯定不如CGRectFrame那樣的設(shè)置更加直接,性能更好.
2.UIView & CALayer的區(qū)別
| 區(qū)別 | UIView | CALayer |
|---|---|---|
| 繼承父類 | UIView:UIResponder:NSObject | CALayer:NSObject |
| 用途 | 可以處理觸摸事件 | 不處理用戶的交互,不參與響應(yīng)事件傳遞 |
| 兩者關(guān)系 | 有一個(gè)CALayer成員變量 eg: view.layer | 是UIView的成員變量 |
| 分工 | 處理交互層事件并包裝各種圖形的簡單設(shè)置 | 底層渲染圖形,支持動(dòng)畫 |
3.事件響應(yīng)鏈
下面這篇文章我已經(jīng)在前幾篇將runloop的時(shí)候提了不止一次,前列建議閱讀,快手的同事大部分都以這個(gè)理解為標(biāo)準(zhǔn)
4. drawrect & layoutsubviews調(diào)用時(shí)機(jī)
layoutSubviews:(相當(dāng)于layoutSubviews()函數(shù))在以下情況下會(huì)被調(diào)用:
- init初始化不會(huì)觸發(fā)layoutSubviews。
- addSubview會(huì)觸發(fā)layoutSubviews。
- 設(shè)置view的Frame會(huì)觸發(fā)layoutSubviews (frame發(fā)生變化觸發(fā))。
- 滾動(dòng)一個(gè)UIScrollView會(huì)觸發(fā)layoutSubviews。
- 旋轉(zhuǎn)Screen會(huì)觸發(fā)父UIView上的layoutSubviews事件。
- 改變一個(gè)UIView大小的時(shí)候也會(huì)觸發(fā)父UIView上的layoutSubviews事件。
- 直接調(diào)用setLayoutSubviews。
drawrect:(drawrect()函數(shù))在以下情況下會(huì)被調(diào)用:
-
drawrect:是在UIViewController的loadView:和ViewDidLoad:方法之后調(diào)用. - 當(dāng)我們調(diào)用
[UIFont的 sizeToFit]后,會(huì)觸發(fā)系統(tǒng)自動(dòng)調(diào)用drawRect: - 當(dāng)設(shè)置UIView的contentMode或者Frame后會(huì)立即觸發(fā)觸發(fā)系統(tǒng)調(diào)用
drawRect: - 直接調(diào)用
setNeedsDisplay設(shè)置標(biāo)記 或setNeedsDisplayInRect:的時(shí)候會(huì)觸發(fā)drawRect:
知識(shí)點(diǎn)擴(kuò)充: 當(dāng)我們操作drawRect方法的時(shí)候?qū)嶋H是在操作內(nèi)存中存放視圖的backingStore區(qū)域,用于后續(xù)圖形的渲染操作,如果不理解可以看下UIView的渲染過程.
5.UI的刷新原理
這個(gè)問題我不知道問的是不是iOS離屏渲染過程,我來簡單的回到一下這個(gè)吧
iOS 的MainRunloop 是一個(gè)60fps 的回調(diào),也就是說16.7ms(毫秒)會(huì)繪制一次屏幕在這過程中要完成以下的工作:
- view的緩沖區(qū)創(chuàng)建
- view內(nèi)容的繪制(如果重寫了 drawRect)
- 接收和處理系統(tǒng)的觸摸事件
我們看到的UI圖形實(shí)際上是CPU和GPU不斷配合工作的結(jié)果.經(jīng)過UIView的渲染過程 后我們的UI會(huì)不間斷的接收系統(tǒng)圖給我們的事件.
由于主線程的runloop 一直在回調(diào),我們的UI就得到了刷新的窗口,是渲染還是處理事件都是因?yàn)閞unloop不斷工作的結(jié)果.前幾篇我們學(xué)過 main線程的runloop默認(rèn)是啟動(dòng)的.因?yàn)槲覀冺憫?yīng)交互.
不知道我這樣回答是否滿足這個(gè)問題的答案.如果回答的不對(duì)煩請下方評(píng)論區(qū)留言 告知我將持續(xù)改進(jìn).
6.隱式動(dòng)畫 & 顯示動(dòng)畫區(qū)別
隱式動(dòng)畫一直存在 如需關(guān)閉需設(shè)置
顯式動(dòng)畫是不存在,如需顯式 要開啟
只需要觀察動(dòng)畫執(zhí)行完成的結(jié)果 比如: 一個(gè)簡單UIView的frame移動(dòng) 如果從A點(diǎn)移動(dòng)到B點(diǎn) 移動(dòng)完成 回到原始位置就是隱式動(dòng)畫
Core Animation 是顯式動(dòng)畫.因?yàn)樗瓤梢灾苯訉?duì)其layer屬性做動(dòng)畫,也可以覆蓋默認(rèn)的圖層行為.
7.imageName&imageWithContentsOfFile區(qū)別
| 區(qū)別 | UIView | imageWithContentsOfFile |
|---|---|---|
| 不同點(diǎn) | 會(huì)圖片緩存到內(nèi)存中 | 無緩存 |
8.什么是離屏渲染
9.多個(gè)相同的圖片,會(huì)重復(fù)加載嗎
不會(huì),GPU有 像素點(diǎn)緩存的mask.
10.圖片是什么時(shí)候解碼的,如何優(yōu)化
是加載到內(nèi)存中,從UIImge->CGImage->CGImageSourceCreateWithData(data) 創(chuàng)建ImageSource變成bitmap位圖,這些工作都是CoreAnimation在圖片被加載到內(nèi)存中存在在backingStore里,送給GPU流水線處理之前被解碼.
如何優(yōu)化
自己手動(dòng)操作圖片的編碼API
CGImageSource開頭的哪些,根據(jù)合理利用時(shí)機(jī)和操作系統(tǒng)資源調(diào)整出一套緩存小加載快的庫.
參考PINRemoteImage或者YYWebImage開源
11.圖片渲染怎么優(yōu)化
可以從陰影,圓角入手.幀率,電量,圖片的鋸齒等等.
12.如果GPU的刷新率超過了iOS屏幕60Hz刷新率是什么現(xiàn)象,怎么解決
現(xiàn)象是 圖形清晰,場景逼真,但是一般arm芯片的GPU 刷新超過60Hz一定會(huì)超級(jí)費(fèi)電,手機(jī)發(fā)熱導(dǎo)致降頻.FPS降低,因?yàn)榈湍芎碾娏坎蛔?無法支持GPU高刷新率
解決辦法只能用xcode自帶工具檢測,看渲染過程哪里可以優(yōu)化.
總結(jié)
簡單回答了一些圖形相關(guān)的問題,大部分都是iOS離屏渲染,這個(gè)地方大家要認(rèn)真學(xué)習(xí).很多資料看起來比較耗時(shí).
推薦文集
收錄:原文地址


