UI

事件處理

事件產(chǎn)生

  1. 當(dāng)用戶點(diǎn)擊屏幕,IOKit收到屏幕操作灶壶,將這次操作封裝為IOHIDEvent對象陕靠,通過mach port將事件發(fā)送給SpringBoard。
  2. SpringBoard是iOS系統(tǒng)的桌面程序鞠评,SpringBoard收到mach port發(fā)送來的事件茂蚓,將事件發(fā)送給在前臺顯示的程序。
  3. 喚醒此程序的main runloop并交給source1處理剃幌,處理內(nèi)部會將事件交給source0處理聋涨,并調(diào)用source0的__UIApplicationHandleEventQueue()函數(shù),在其中將事件轉(zhuǎn)換為UIEvent负乡。
  4. 調(diào)用UIApplocation的sendEvent:方法

事件傳遞&響應(yīng)

傳遞:

  1. UIApplication接收到事件牛郑,將事件傳遞給keyWindow。
  2. keyWindow遍歷subViews的hitTest:withEvent:方法敬鬓,找到點(diǎn)擊區(qū)域合適的試圖來處理淹朋。
  3. UIView的子視圖也會遍歷其subViews的hitTest:withEvent:方法。
  4. 找到點(diǎn)擊區(qū)域內(nèi)钉答,且處于最上方的視圖础芍,將視圖逐步返回給UIApplication。
  5. 在查找第一響應(yīng)者的過程中数尿,形成了響應(yīng)鏈仑性。

響應(yīng):

  1. 應(yīng)用調(diào)用第一響應(yīng)者處理事件,
  2. 如果第一響應(yīng)者不能處理事件右蹦,則調(diào)用其nextResponder方法诊杆,一直找到響應(yīng)鏈中能夠處理該事件的對象歼捐。
  3. 最后到UIApplication后仍然沒有處理該事件的對象,則該事件被廢棄
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    if (self.alpha <= 0.01 || self.userInteractionEnabled == NO || self.hidden) {
        return nil;
    }
    
    BOOL inside = [self pointInside:point withEvent:event];
    if (inside) {
        NSArray *subViews = self.subviews;
        // 對子視圖從上向下找
        for (NSInteger i = subViews.count - 1; i >= 0; i--) {
            UIView *subView = subViews[i];
            CGPoint insidePoint = [self convertPoint:point toView:subView];
            UIView *hitView = [subView hitTest:insidePoint withEvent:event];
            if (hitView) {
                return hitView;
            }
        }
        return self;
    }
    return nil;
}

事件攔截

如果想讓指定試圖來響應(yīng)事件晨汹,不再向其子試圖繼續(xù)傳遞事件豹储,可以通過重寫如下

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    return self;
}

事件轉(zhuǎn)發(fā)

SuperView的SubView超出了其視圖范圍,如果點(diǎn)擊SubView在試圖外面的部分則不能響應(yīng)時間淘这“郏可以通過重寫pointInside:withEvent:方法,將相應(yīng)區(qū)域擴(kuò)大為虛線區(qū)域铝穷,包括SuperView的所有子試圖钠怯,即可以讓子試圖響應(yīng)事件。

事件逐級傳遞

如果想讓響應(yīng)者中每一級都可以響應(yīng)事件曙聂,可以在每級UIResponder中都實(shí)現(xiàn)touches并調(diào)用super晦炊。

UIControl > 手勢 > UIResponder

iOS渲染原理 & UI的刷新原理

CPU 和 GPU 的設(shè)計(jì)目的分別是什么?

CPU是運(yùn)算核心和控制核心宁脊,需要很強(qiáng)的運(yùn)算通用型刽锤,兼容各種數(shù)據(jù)類型。
GPU則面對的是類型統(tǒng)一朦佩,更大的運(yùn)算任務(wù)并思。

計(jì)算機(jī)圖像渲染流水線的大致流程是什么?

Application(應(yīng)用處理階段:得到圖元) -> Geometry Processing(幾何處理階段:處理圖元) -> Rasterization(光柵化階段:圖元轉(zhuǎn)換為像素) -> Pixel Processing(處理像素语稠,得到位圖)

Framebuffer 幀緩沖器的作用是什么宋彼?

存儲渲染之后的像素信息,方便控制器讀取仙畦。

Screen Tearing 屏幕撕裂是怎么造成的输涕?

控制器讀取幀緩存器上半部時,新的幀以及渲染完成放入幀緩存器中慨畸,控制器讀取的不是同一幀圖像莱坎,導(dǎo)致屏幕撕裂。

如何解決屏幕撕裂的問題寸士?

引入垂直同步Vsync+雙緩沖機(jī)制Double Buffering
在屏幕掃描上一幀加載完成之前新渲染的幀數(shù)據(jù)放入back buffer里檐什,當(dāng)當(dāng)前幀加載完成后發(fā)出Vsync信號去通知控制器去將back buffer中的內(nèi)容置換到frame buffer中。

掉幀是怎么產(chǎn)生的弱卡?

如果在接收到Vsync信號時CPU和GPU還沒有渲染好新的位圖乃正,控制器就不會去替換frame buffer中的位圖。這時候屏幕就會重新掃描呈現(xiàn)出上一幀一摸一樣的畫面婶博,這就是掉幀瓮具。

CoreAnimation 的職責(zé)是什么?

Core Animation是一個復(fù)合引擎,主要職責(zé)包括:渲染 構(gòu)建 實(shí)現(xiàn)動畫名党,盡可能快的組合屏幕上的CALayer叹阔,并且被存儲為樹狀層級結(jié)構(gòu)

UIView 和 CALayer 是什么關(guān)系?有什么區(qū)別传睹?

創(chuàng)建UIView都會自動創(chuàng)建一個CALayer耳幢,為自身提供存儲bitmap的地方,并將自身固定設(shè)置為CALayer的代理蒋歌。

  1. 我們對 UIView 的層級結(jié)構(gòu)非常熟悉,由于每個 UIView 都對應(yīng) CALayer 負(fù)責(zé)頁面的繪制委煤,所以 CALayer 也具有相應(yīng)的層級結(jié)構(gòu)堂油。
  2. CALayer 繼承自 NSObject,UIView 由于要負(fù)責(zé)交互事件碧绞,所以繼承自 UIResponder府框。
  3. 因?yàn)?UIView 只對 CALayer 的部分功能進(jìn)行了封裝,而另一部分如圓角讥邻、陰影迫靖、邊框等特效都需要通過調(diào)用 layer 屬性來設(shè)置。
  4. CALayer 不負(fù)責(zé)點(diǎn)擊事件兴使,所以不響應(yīng)點(diǎn)擊事件系宜,而 UIView 會響應(yīng)。

為什么會同時有 UIView 和 CALayer发魄,能否合成一個盹牧?

  1. 這樣設(shè)計(jì)的主要原因就是為了職責(zé)分離,拆分功能励幼,方便代碼的復(fù)用汰寓。
  2. iOS 有 UIKit 和 UIView,OS X 則是AppKit 和 NSView苹粟。

渲染流水線中有滑,CPU 會負(fù)責(zé)哪些任務(wù)?

離屏渲染為什么會有效率問題嵌削?

離屏渲染需要先額外創(chuàng)建離屏緩沖區(qū)毛好,將提前渲染好的內(nèi)容放入,之后將Offscreen Buffer中的內(nèi)容進(jìn)一步疊加 渲染 完成后將結(jié)果切換到FrameBuffer中苛秕。

  1. Offscreen Buffer本身需要額外空間睛榄。
  2. 離屏渲染的開銷很大,一旦離屏渲染的內(nèi)容過多想帅,很容易造成掉幀场靴。

什么時候應(yīng)該使用離屏渲染?

  1. 一些特殊效果需要額外使用Offscreen Buffer來保存渲染的中間狀態(tài)。(系統(tǒng)自動觸發(fā):陰影 圓角)
  2. 效率目的旨剥,可以將內(nèi)容提前渲染保存在Offscreen Buffer中咧欣,達(dá)到復(fù)用的目的。(主動觸發(fā):通過CALayer shouldRasterize)

shouldRasterize 光柵化是什么轨帜?

開啟光柵化后魄咕,會觸發(fā)離屏渲染,Render Server會強(qiáng)制將CALayer的渲染位圖結(jié)果bitmap保存起來蚌父,下次可直接復(fù)用哮兰。

有哪些常見的觸發(fā)離屏渲染的情況?

  1. 使用了mask的layer(layer.mask)
  2. 需要進(jìn)行裁剪的layer(layer.masksToBounds/view.clipsToBounds)
  3. 設(shè)置了組透明度為YES苟弛,并且透明度不為1的layer(layer.opacity)
  4. 添加了投影的layer(layer.shadow)
  5. 采用了光柵化的layer(layer.shouldRasterize)
  6. 繪制了文字的layer(UILabel, CATextLayer, Core Text)

圓角觸發(fā)的離屏渲染有哪些解決方案喝滞?

  1. 使用帶圓角的圖片。
  2. 在添加一個和背景相同的遮罩mask覆蓋在最上面膏秫,蓋住四個角右遭。
  3. UIBezierPath貝塞爾曲線。
  4. CoreGraphics缤削,重寫drawRect

重寫 drawRect 方法會觸發(fā)離屏渲染嗎窘哈?

不會,雖然drawRect會將GPU中的渲染操作放入CPU中來做亭敢,并且需要額外開辟一個空間來做滚婉,這和標(biāo)準(zhǔn)意義上的離屏渲染不同。

drawrect & layoutsubviews調(diào)用時機(jī)

layoutsubviews:

  1. addSubView
  2. 修改frame
  3. 滾動UISCrollView
  4. 直接調(diào)用setNeedsLayout

drawrect:

  1. Controller->loadView 和 -> viewDidLoad之后
  2. sizeToFit之后
  3. 設(shè)置contentMode屬性值為UIViewContentModeRedraw帅刀。那么將在每次設(shè)置或更改frame的時候自動調(diào)用drawRect:
  4. 直接調(diào)用setNeedsDisplay

Talbleview 的性能優(yōu)化

  1. 快速滑動時先不加載TalbleviewCell上的圖片满哪,等將要停止時再去加載當(dāng)前Cell附近Cell的圖片。
  2. 監(jiān)聽RunLoop閑時再去做圖片的加載劝篷。

AutoLayout的原理哨鸭,性能如何

根據(jù)約束條件算出frame,在復(fù)雜界面異常差娇妓。

隱式動畫 & 顯示動畫區(qū)別

imageName & imageWithContentsOfFile區(qū)別

imageName:

  1. 系統(tǒng)會緩存加載的圖片

imageWithContentsOfFile:

  1. 不會被緩存像鸡,每次都需要重新加載
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市哈恰,隨后出現(xiàn)的幾起案子只估,更是在濱河造成了極大的恐慌,老刑警劉巖着绷,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蛔钙,死亡現(xiàn)場離奇詭異,居然都是意外死亡荠医,警方通過查閱死者的電腦和手機(jī)吁脱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進(jìn)店門桑涎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人兼贡,你說我怎么就攤上這事攻冷。” “怎么了遍希?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵等曼,是天一觀的道長。 經(jīng)常有香客問我凿蒜,道長禁谦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任废封,我火速辦了婚禮州泊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘虱饿。我一直安慰自己拥诡,他們只是感情好触趴,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布氮发。 她就那樣靜靜地躺著,像睡著了一般冗懦。 火紅的嫁衣襯著肌膚如雪爽冕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天披蕉,我揣著相機(jī)與錄音颈畸,去河邊找鬼。 笑死没讲,一個胖子當(dāng)著我的面吹牛眯娱,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播爬凑,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼徙缴,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了嘁信?” 一聲冷哼從身側(cè)響起于样,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎潘靖,沒想到半個月后穿剖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡卦溢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年糊余,在試婚紗的時候發(fā)現(xiàn)自己被綠了秀又。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡啄刹,死狀恐怖涮坐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情誓军,我是刑警寧澤袱讹,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站昵时,受9級特大地震影響捷雕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜壹甥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一救巷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧句柠,春花似錦浦译、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至谜酒,卻和暖如春叹俏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背僻族。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工粘驰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人述么。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓蝌数,卻偏偏與公主長得像,于是被迫代替她去往敵國和親度秘。 傳聞我的和親對象是個殘疾皇子顶伞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評論 2 353

推薦閱讀更多精彩內(nèi)容

  • UITableView 復(fù)用機(jī)制 為什么要用重用機(jī)制? 當(dāng)UITableView滾動時敷钾,如果不用重用機(jī)制枝哄,會重復(fù)初...
    愛玩游戲的iOS菜鳥閱讀 554評論 0 0
  • UI視圖相關(guān) UITableView 事件傳遞&視圖響應(yīng) 圖像顯示原理 卡頓&掉幀 繪制原理&異步繪制 離屏渲染 ...
    Sendom閱讀 314評論 0 0
  • http://blog.csdn.net/guojin08/article/details/60773120 屏幕...
    pony23閱讀 898評論 0 2
  • UItableView 重用機(jī)制 一般在iOS中,tableview的重用機(jī)制阻荒,我們在- (UITableView...
    叔簡閱讀 723評論 0 3
  • UITableView相關(guān) 事件傳遞&視圖響應(yīng) 系統(tǒng)的UI事件傳遞機(jī)制是怎么樣的 ? 使UITableView滾動...
    木子奕閱讀 1,073評論 0 5