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


