系統(tǒng)化學(xué)習(xí),知其然,知其所以然
一、簡(jiǎn)介
在iOS中,可以使用 Windows 和 Views 在屏幕上顯示應(yīng)用程序的內(nèi)容。 Windows 本身沒有任何可見的內(nèi)容,為 App 展示 Views 提供一個(gè) root 容器。 Views 有2個(gè)任務(wù):
- 使用 Window 一部分或者全部來展示指定內(nèi)容的容器;
- 管理子視圖。
所以每個(gè) App 至少有一個(gè) Window 和一個(gè) View 來顯示其內(nèi)容。
UIKit 和其他 System Frameworks 提供了預(yù)定義的 Views,可以使用它來呈現(xiàn)你的內(nèi)容。 這些 Views 的范圍從簡(jiǎn)單的按鈕和文本標(biāo)簽到更復(fù)雜的視圖,如table views、picker views 和 scroll views。 在預(yù)定義視圖滿足不了需要的地方,還可以自定義 View。
二、View、Window架構(gòu)
無論使用系統(tǒng)視圖還是創(chuàng)建自己的自定義視圖,都需要了解 UIView 和 UIWindow 類提供的基礎(chǔ)功能。 這些類提供先進(jìn)的工具來管理視圖的布局和表示。 了解這些類的工作方式對(duì)于及時(shí)調(diào)整 View 非常重要。
2.1 View 基礎(chǔ)架構(gòu)
View在屏幕上定義了一個(gè)矩形區(qū)域,并處理該區(qū)域中的繪圖和觸摸事件。也可以作為其他視圖的父項(xiàng),并協(xié)調(diào)這些視圖的布局和大小。
View 與 Layer 一起工作來處理視圖內(nèi)容的渲染和動(dòng)畫。 UIKit中的每個(gè)View都有一個(gè)Layer對(duì)象(通常是CALayer類的一個(gè)實(shí)例)支持,該對(duì)象負(fù)責(zé)渲染工作。一般情況下執(zhí)行的大多數(shù)操作應(yīng)該通過UIView接口;但是在需要更多地控制視圖的渲染或動(dòng)畫行為的情況下,可以通過其Layer執(zhí)行操作。
sequenceDiagram
UIView->>CALayer: 持有,通過layer屬性訪問
CALayer->>UIView: 處理渲染和動(dòng)畫相關(guān)內(nèi)容
下圖有助于理解View和Layer關(guān)系
[圖片上傳失敗...(image-910a4c-1511255110112)]
Layer對(duì)象的使用對(duì)性能有重要的影響。 所以
- 盡可能少地調(diào)用View對(duì)象的實(shí)際繪圖代碼,
- 并且當(dāng)調(diào)用代碼時(shí),結(jié)果被Core Animation緩存,并盡可能被重用。
重用已有內(nèi)容消除了一般情況下更新視圖需要經(jīng)歷的的耗時(shí)。 當(dāng)動(dòng)畫中有重復(fù)內(nèi)容時(shí),重用非常重要,這種重復(fù)使用比創(chuàng)建新內(nèi)容代價(jià)小得多。
2.2 View 層次結(jié)構(gòu)和子視圖管理
除了提供自己的內(nèi)容之外,視圖還可以充當(dāng)其他視圖的容器。當(dāng)一個(gè)視圖包含另一個(gè)視圖時(shí),兩個(gè)視圖之間會(huì)創(chuàng)建一個(gè)父子關(guān)系。
sequenceDiagram
父視圖->>子視圖: 是子視圖的superview
子視圖->>父視圖: 是父視圖的subview
Superview將其子視圖存儲(chǔ)在有序數(shù)組中,并且該數(shù)組中的順序也會(huì)影響每個(gè)子視圖的可見性。如果兩個(gè)subview彼此重疊,則最后添加的子視圖(或移動(dòng)到子視圖數(shù)組的末尾)會(huì)出現(xiàn)在另一個(gè)之上。Subview的顯示效果受Superview影響,例如位置、大小、透明度等。
。
2.3 The View Drawing Cycle
graph LR
首次顯示-->繪制內(nèi)容
繪制內(nèi)容-->獲取快照
獲取快照-->展示快照
展示快照-->內(nèi)容更改
內(nèi)容更改-->首次顯示
UIView按需繪制模型來呈現(xiàn)內(nèi)容。當(dāng)一個(gè)視圖第一次出現(xiàn)在屏幕上時(shí),系統(tǒng)按要求它畫出其內(nèi)容。系統(tǒng)捕獲此內(nèi)容的快照,并將該快照用作視圖的視覺表示。如果你永遠(yuǎn)不改變視圖的內(nèi)容,視圖的繪圖代碼可能永遠(yuǎn)不會(huì)再被調(diào)用。大多數(shù)涉及視圖的操作都會(huì)重用快照?qǐng)D像。如果您更改內(nèi)容,則通知系統(tǒng)視圖已更改。該視圖然后重復(fù)繪制視圖并捕獲新結(jié)果的快照的過程。
當(dāng)你的視圖的內(nèi)容改變時(shí),你不要直接重繪這些改變。而是使用
- (void)setNeedsDisplay;
或
- (void)setNeedsDisplayInRect:(CGRect)rect;
方法使視圖失效。這些方法告訴系統(tǒng),視圖的內(nèi)容改變了,需要在下一個(gè)機(jī)會(huì)重新繪制。在啟動(dòng)任何繪圖操作之前,系統(tǒng)等待當(dāng)前運(yùn)行循環(huán)的結(jié)束。這種延遲使您有機(jī)會(huì)使多個(gè)視圖失效,從您的層次結(jié)構(gòu)添加或刪除視圖,隱藏視圖,調(diào)整視圖大小,并一次重新定位視圖。然后你所做的所有改變都會(huì)同時(shí)反映出來。
注:更改View的幾何屬性不會(huì)自動(dòng)導(dǎo)致系統(tǒng)重新繪制視圖的內(nèi)容。視圖的contentMode屬性確定如何對(duì)視圖幾何體的更改。大多數(shù)contentMode在視圖的邊界內(nèi)拉伸或重新定位現(xiàn)有的快照,而不是創(chuàng)建一個(gè)新的快照。
當(dāng)呈現(xiàn)視圖的內(nèi)容時(shí),實(shí)際的繪圖過程會(huì)根據(jù)視圖及其配置而變化。系統(tǒng)視圖通常實(shí)現(xiàn)私有繪圖方法來呈現(xiàn)其內(nèi)容。這些相同的系統(tǒng)視圖經(jīng)常公開可用于配置視圖的實(shí)際外觀的接口。對(duì)于自定義UIView子類,通常會(huì)覆蓋視圖的drawRect:方法,并使用該方法繪制視圖的內(nèi)容。還有其他方法可以提供視圖的內(nèi)容,比如直接設(shè)置底層的內(nèi)容,但是覆蓋drawRect:方法是最常用的技術(shù)。
2.4 顯示模式 Content Modes
每個(gè)視圖都有一個(gè)Content Mode,用于控制視圖如何響應(yīng)其內(nèi)容以適應(yīng)視圖幾何屬性的變化以及是否回收其內(nèi)容。當(dāng)視圖第一次顯示時(shí),它像往常一樣渲染其內(nèi)容,并將結(jié)果捕獲在底層位圖中。之后,對(duì)視圖幾何屬性的更改并不總是會(huì)導(dǎo)致重新創(chuàng)建位圖。相反,contentMode屬性中的值決定是否縮放位圖以適應(yīng)新的邊界,或者只是固定到視圖的一個(gè)角或邊緣。
視圖的Content Mode在執(zhí)行以下操作時(shí)用到:
- 更改 View 的 frame 或 bounds 的寬度或高度。
- view's transform 有 scaling 參數(shù)變化。
默認(rèn)情況下,大多數(shù)視圖的contentMode屬性被設(shè)置為UIViewContentModeScaleToFill,這會(huì)導(dǎo)致視圖的內(nèi)容被縮放以適應(yīng)新的幀大小。下圖顯示了一些可用的內(nèi)容模式的結(jié)果。從圖中可以看出,并不是所有的內(nèi)容模式都會(huì)導(dǎo)致視圖的邊界被完全填充,而那些內(nèi)容模式可能會(huì)扭曲視圖的內(nèi)容

慎用UIViewContentModeRedraw 屬性,尤其是 System Views
2.5 拉伸視圖 Stretchable Views
可以指定視圖的一部分為可拉伸的,以便當(dāng)視圖的大小改變時(shí),只有可拉伸部分的內(nèi)容受到影響。
通常在按鈕或其他視圖中使用可拉伸區(qū)域,其中部分視圖定義了可重復(fù)的圖案。 指定的可拉伸區(qū)域可以允許沿視圖的一個(gè)或兩個(gè)軸伸展。 當(dāng)然,當(dāng)沿著兩個(gè)軸伸展視圖時(shí),視圖的邊緣也必須定義可重復(fù)的圖案以避免任何失真。
如圖顯示了這種扭曲是如何在視圖中體現(xiàn)出來的。 來自每個(gè)視圖的原始像素的顏色被復(fù)制以填充大視圖中的對(duì)應(yīng)區(qū)域。
[圖片上傳失敗...(image-3ca96e-1511255110112)]
可以使用contentStretch屬性指定視圖的可拉伸區(qū)域。該屬性接受一個(gè)矩形,其值被規(guī)范化為0.0到1.0的范圍。當(dāng)拉伸視圖時(shí),系統(tǒng)將這些歸一化值乘以視圖的當(dāng)前邊界和比例因子,以確定哪些像素或像素需要拉伸。每當(dāng)視圖邊界發(fā)生變化時(shí),使用規(guī)范化值就可以減少更新contentStretch屬性的必要性。
contentStretch屬性已廢棄,使用新接口
視圖的 Content Mode 在確定如何使用視圖的可拉伸區(qū)域方面也起著重要作用。僅當(dāng) Content Mode 會(huì)導(dǎo)致視圖的內(nèi)容被縮放時(shí)才使用可伸縮區(qū)域。這意味著只有
UIViewContentModeScaleToFill,
UIViewContentModeScaleAspectFit,
UIViewContentModeScaleAspectFill
才支持可伸縮視圖。如果指定將內(nèi)容固定到邊或角的Content Mode(因此實(shí)際上不會(huì)縮放內(nèi)容),則視圖將忽略可拉伸區(qū)域。
注意:在為視圖指定背景時(shí),建議使用contentStretch屬性來創(chuàng)建可拉伸的UIImage對(duì)象。可伸縮視圖完全在Core Animation層中處理,通常可以提供更好的性能。
2.6 內(nèi)置動(dòng)畫支持 Built-In Animation Support
在每個(gè)視圖背后都有一個(gè)圖層對(duì)象的好處之一是可以輕松地動(dòng)畫許多與視圖相關(guān)的更改。動(dòng)畫是向用戶傳遞信息的有效方法,在設(shè)計(jì)應(yīng)用程序時(shí)應(yīng)始終考慮動(dòng)畫。 UIView類的許多屬性都是可以動(dòng)畫的 - 也就是說,半自動(dòng)支持存在從一個(gè)值到另一個(gè)值的動(dòng)畫。要為其中一個(gè)動(dòng)畫屬性執(zhí)行動(dòng)畫,您只需執(zhí)行以下操作:
- 告訴UIKit你想要執(zhí)行一個(gè)動(dòng)畫
- 更改屬性的值。
你可以在UIView對(duì)象上動(dòng)畫的屬性如下:
- frame — Use this to animate position and size changes for the view.
- bounds — Use this to animate changes to the size of the view.
- center — Use this to animate the position of the view.
- transform — Use this to rotate or scale the view.
- alpha — Use this to change the transparency of the view.
- backgroundColor — Use this to change the background color of the view.
- contentStretch — Use this to change how the view’s contents stretch.
動(dòng)畫非常重要的一個(gè)地方是從一組視圖轉(zhuǎn)換到另一組視圖。通常,使用視圖控制器來管理與用戶界面各部分之間的重大更改相關(guān)的動(dòng)畫。例如,對(duì)于涉及從較高層級(jí)到較低層級(jí)的接口,通常使用導(dǎo)航控制器來管理View直接的跳轉(zhuǎn)和顯示??梢栽趘iew controller跳轉(zhuǎn)動(dòng)畫不能滿足需要時(shí),使用Views進(jìn)行動(dòng)畫跳轉(zhuǎn)。
除了使用UIKit類創(chuàng)建的動(dòng)畫外,還可以使用Core Animation圖層創(chuàng)建動(dòng)畫。底層圖層可以更好地控制動(dòng)畫的時(shí)間和屬性。
三、視圖幾何和坐標(biāo)系統(tǒng)
UIKit坐標(biāo)原點(diǎn)
[圖片上傳失敗...(image-b47bbf-1511255110112)]
(注意:Core Graphics 和 OpenGL ES 左邊原點(diǎn)在左下角)
3.1 Frame、Bounds、Center關(guān)系
| 屬性 | 詳情 |
|---|---|
| Frame | 在其父視圖的坐標(biāo)系中指定視圖的大小和位置 |
| Bounds | 在視圖自己的本地坐標(biāo)系統(tǒng)中指定視圖(及其內(nèi)容原點(diǎn))的大小。 |
| Center | 在其父視圖的坐標(biāo)系中指定視圖中心點(diǎn) |
雖然以上三者都可以獨(dú)立修改,但是修改其中一個(gè)會(huì)影響到其他值。
| 屬性 | 影響值 |
|---|---|
| Frame | Bounds、Center |
| Bounds | Frame |
| Center | Frame |
下圖有助于理解三者關(guān)系

3.2 坐標(biāo)系轉(zhuǎn)換(Coordinate System Transformations)
坐標(biāo)系轉(zhuǎn)換提供了一種快速方便地更改視圖(或其內(nèi)容)的方法。仿射變換是一個(gè)數(shù)學(xué)矩陣,指定一個(gè)坐標(biāo)系中的點(diǎn)如何映射到不同坐標(biāo)系中的點(diǎn)。您可以將仿射變換應(yīng)用于整個(gè)視圖,以相對(duì)于其超視圖更改視圖的大小,位置或方向。您還可以在繪圖代碼中使用仿射變換對(duì)各個(gè)渲染內(nèi)容執(zhí)行相同類型的操作。
如何應(yīng)用仿射變換取決于 context:
要修改整個(gè)視圖,請(qǐng)?jiān)谝晥D的transform屬性中修改仿射變換。Translating, Scaling, and Rotating Views
要修改視圖的drawRect:方法中特定的內(nèi)容片段,請(qǐng)修改與 active graphics context 關(guān)聯(lián)的仿射變換。Drawing and Printing Guide for iOS
當(dāng)實(shí)現(xiàn)動(dòng)畫時(shí),通常會(huì)修改視圖的transform屬性。例如,您可以使用此屬性來創(chuàng)建圍繞其中心點(diǎn)旋轉(zhuǎn)的視圖的動(dòng)畫。不要使用此屬性對(duì)您的視圖進(jìn)行永久更改,例如在其父視圖的坐標(biāo)空間內(nèi)修改其視圖的位置或大小。對(duì)于這種類型的更改,您應(yīng)該修改視圖的 frame 屬性。
注意:修改視圖的transform屬性時(shí),所有的轉(zhuǎn)換都是相對(duì)于視圖的中心點(diǎn)執(zhí)行的。
在您的視圖的drawRect:方法中,使用仿射變換來定位和定位您打算繪制的項(xiàng)目。不是在視圖的某個(gè)位置固定對(duì)象的位置,而是相對(duì)于固定點(diǎn)(通常為(0,0))創(chuàng)建每個(gè)對(duì)象并在繪制之前立即使用變換來定位對(duì)象。這樣,如果對(duì)象的位置在您的視圖中發(fā)生變化,您所要做的就是修改變換,這比在新位置重新創(chuàng)建對(duì)象要快得多,成本也更低。您可以使用CGContextGetCTM函數(shù)檢索與圖形上下文關(guān)聯(lián)的仿射變換,并且可以使用相關(guān)的核心圖形函數(shù)在繪圖期間設(shè)置或修改此變換。
當(dāng)前變換矩陣(CTM)是在任何給定時(shí)間使用的仿射變換。在操作整個(gè)視圖的幾何圖形時(shí),CTM是存儲(chǔ)在視圖的transform屬性中的仿射變換。在drawRect:方法中,CTM是與活動(dòng)圖形上下文關(guān)聯(lián)的仿射變換。
每個(gè)子視圖的坐標(biāo)系建立在其祖先的坐標(biāo)系上。所以,當(dāng)你修改一個(gè)視圖的transform屬性時(shí),這個(gè)改變會(huì)影響視圖及其所有的子視圖。但是,這些更改僅影響屏幕上視圖的最終呈現(xiàn)。由于每個(gè)視圖都是繪制其內(nèi)容,并將其子視圖相對(duì)于其邊界進(jìn)行布局,所以在繪制和布局過程中可以忽略其超視圖的變換。
[圖片上傳失敗...(image-b31b78-1511255110112)]
重要提示:如果視圖的transform屬性不是 identity transform,則該視圖的frame屬性值是未定義的,必須忽略。 將變換應(yīng)用于視圖時(shí),必須使用視圖的邊界和中心屬性來獲取視圖的大小和位置。 其子視圖的 frame 仍然有效,因?yàn)樗鼈兪窍鄬?duì)于它的 bounds 屬性。
3.3 點(diǎn)和像素(Points Versus Pixels)
一點(diǎn)不一定對(duì)應(yīng)于屏幕上的一個(gè)像素。 對(duì)應(yīng)關(guān)系由操作系統(tǒng)決定,不需要關(guān)注。
四、視圖交互過程(The Runtime Interaction Model for Views)
每當(dāng)用戶與您的用戶界面進(jìn)行交互時(shí),或者您自己的代碼以編程方式更改某些內(nèi)容時(shí),都會(huì)在UIKit內(nèi)部發(fā)生一系列復(fù)雜的事件來處理該交互。
在這個(gè)序列的特定時(shí)間點(diǎn),UIKit會(huì)調(diào)用您的視圖類,并讓他們有機(jī)會(huì)代表您的應(yīng)用程序進(jìn)行響應(yīng)。理解這些標(biāo)注點(diǎn)對(duì)于理解視圖適合系統(tǒng)的位置很重要。圖1-7顯示了用戶觸摸屏幕開始的事件的基本順序,以圖形系統(tǒng)作為響應(yīng)更新屏幕內(nèi)容結(jié)束。任何由程序啟動(dòng)的動(dòng)作也會(huì)發(fā)生相同的事件序列。

以下步驟將圖中的事件序列進(jìn)一步分解,并解釋每個(gè)階段會(huì)發(fā)生什么情況,以及應(yīng)用程序如何響應(yīng)。
用戶觸摸屏幕
硬件將觸發(fā)事件派發(fā)到UIKit
UIKit將觸摸事件封裝到UIEvent對(duì)象中,并將其分派到相應(yīng)的View。
-
View處理事件并做出響應(yīng)。例如,
- 更改view或其subviews的屬性(frame,bounds,alpha等)。
- 調(diào)用setNeedsLayout方法將view(或subview)標(biāo)記為需要更新布局。
- 調(diào)用setNeedsDisplay或setNeedsDisplayInRect:方法將view(或subview)標(biāo)記為需要重繪。
- 通知控制器關(guān)于某些數(shù)據(jù)的更改。
-
如果view的幾何屬性改變,則UIKit根據(jù)以下規(guī)則更新subview:
- 如果為view設(shè)置了自動(dòng)調(diào)整規(guī)則,則UIKit會(huì)根據(jù)這些規(guī)則調(diào)整每個(gè)視圖。Handling Layout Changes Automatically Using Autoresizing Rules
- 如果view實(shí)現(xiàn)了layoutSubviews方法,UIKit會(huì)調(diào)用它。
可以在自定義視圖中重寫此方法,并使用它來調(diào)整任何子視圖的位置和大小。例如,提供大的可滾動(dòng)區(qū)域的視圖將需要使用多個(gè)子視圖作為“圖塊”,而不是創(chuàng)建較大視圖(內(nèi)存原因)。執(zhí)行此方法時(shí),視圖將隱藏或重定位不在屏幕上的任何子視圖,并使用它們繪制新開的內(nèi)容。其中,視圖的布局代碼也可以使任何需要重繪的視圖失效。
-
如果任何view的任何部分被標(biāo)記為需要重繪,UIKit會(huì)要求view重繪自己。
- 對(duì)于明確定義drawRect:方法的自定義視圖,UIKit會(huì)調(diào)用此方法。這個(gè)方法的實(shí)現(xiàn)應(yīng)該盡可能快的重繪視圖的指定區(qū)域,而不是其他的。此時(shí)不要進(jìn)行額外的布局更改,也不要對(duì)應(yīng)用程序的數(shù)據(jù)模型進(jìn)行其他更改。此方法的目的是更新視圖的視覺內(nèi)容。
- 標(biāo)準(zhǔn)系統(tǒng)視圖通常不執(zhí)行drawRect:方法,但是管理他們的繪圖。
任何較新的視圖都與應(yīng)用程序的其余可見內(nèi)容合成,并發(fā)送到graphics hardware進(jìn)行顯示
Graphics hardware 將渲染的內(nèi)容傳輸?shù)狡聊簧稀?/p>
在前面的一系列步驟中,自定義view的主要集成點(diǎn)是:
- 事件處理方法:
- (void)touchesBegan:(NSSet<UITouch *> *)touches
withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet<UITouch *> *)touches
withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet<UITouch *> *)touches
withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet<UITouch *> *)touches
withEvent:(UIEvent *)event;
layoutSubviews方法
drawRect:方法
這些是視圖中最常用的重寫方法,但是可能不需要重寫所有這些方法。
如果使用手勢(shì)識(shí)別器來處理事件,則不需要重寫任何事件處理方法。
如果您的視圖不包含子視圖或其大小不會(huì)更改,則沒有理由重寫layoutSubviews方法。
只有在視圖的內(nèi)容可以在運(yùn)行時(shí)更改并且使用原生技術(shù)(如UIKit或Core Graphics)進(jìn)行繪制時(shí),才需要drawRect:方法。
這些是主要的整合點(diǎn),但不是所有的。其他請(qǐng)參考 UIView。
五、 提升使用效率 Tips for Using Views Effectively
當(dāng)系統(tǒng)提供的標(biāo)準(zhǔn)視圖不能滿足需要時(shí),需要自定義view。自定義view需要注意優(yōu)化性能,可以從以下幾點(diǎn)考慮
5.1 Views Do Not Always Have a Corresponding View Controller
視圖和視圖控制器之間很少有一對(duì)一的關(guān)系。視圖控制器的工作是管理一個(gè)視圖層次結(jié)構(gòu),通常由多個(gè)視圖組成,用于實(shí)現(xiàn)一些獨(dú)立的功能。對(duì)于iPhone應(yīng)用程序,每個(gè)視圖層次結(jié)構(gòu)通常填充整個(gè)屏幕,但對(duì)于iPad應(yīng)用程序,視圖層次結(jié)構(gòu)可能只填充屏幕的一部分。
在設(shè)計(jì)應(yīng)用程序的用戶界面時(shí),考慮視圖控制器將扮演的角色非常重要。視圖控制器提供了許多重要的行為,例如協(xié)調(diào)屏幕上的視圖顯示,協(xié)調(diào)從屏幕上移除這些視圖,響應(yīng)低內(nèi)存警告釋放內(nèi)存,以及響應(yīng)接口方向更改而旋轉(zhuǎn)視圖。避免這些行為可能會(huì)導(dǎo)致您的應(yīng)用程序出現(xiàn)錯(cuò)誤或意外的行為。
5.2 盡量減少自定義繪圖(Minimize Custom Drawing)
盡量使用系統(tǒng)提供的標(biāo)準(zhǔn)view,不行試試組合view,實(shí)在不行再去自定義繪圖。
5.3 Take Advantage of Content Modes
Content Modes式可以減少重繪視圖的時(shí)間。 默認(rèn)情況下,視圖使用 UIViewContentModeScaleToFill ,該 Content Modes 縮放視圖的現(xiàn)有內(nèi)容以適合視圖的框架矩形。 您可以根據(jù)需要更改此模式以不同的方式調(diào)整您的內(nèi)容,但是如果可以的話,應(yīng)該避免使用 UIViewContentModeRedraw 內(nèi)容模式。 無論使用哪一種Content Modes,都可以通過調(diào)用 setNeedsDisplay 或 setNeedsDisplayInRect:來強(qiáng)制視圖重繪其內(nèi)容。
5.4 盡量使用不透明View(Declare Views as Opaque Whenever Possible)
UIKit使用每個(gè)視圖的opaque屬性來確定視圖是否可以優(yōu)化合成操作。建議opaque = YES, 告訴UIKit它不需要在視圖后面呈現(xiàn)任何內(nèi)容, 較少的渲染會(huì)導(dǎo)致您的繪圖代碼的性能提高。 當(dāng)然,如果將opaque屬性設(shè)置為YES,則視圖必須用完全不透明的內(nèi)容完全填充其bounds。
5.5 滾動(dòng)時(shí)調(diào)整視圖的繪圖(Adjust Your View’s Drawing Behavior When Scrolling)
滾動(dòng)可以在很短的時(shí)間內(nèi)產(chǎn)生大量的視圖更新。如果您的視圖的繪制代碼沒有適當(dāng)?shù)卣{(diào)整,則視圖的滾動(dòng)性能可能會(huì)很低。在開始滾動(dòng)操作時(shí),不要試圖確保視圖的內(nèi)容始終處于原始狀態(tài),而應(yīng)考慮更改視圖的行為。例如,您可以暫時(shí)降低渲染內(nèi)容的質(zhì)量,或在滾動(dòng)正在進(jìn)行時(shí)更改內(nèi)容模式。當(dāng)滾動(dòng)停止時(shí),您可以將視圖返回到之前的狀態(tài),并根據(jù)需要更新內(nèi)容。
5.6 不要通過嵌入子視圖來自定義控件(Do Not Customize Controls by Embedding Subviews)
盡管在技術(shù)上可以將子視圖添加到標(biāo)準(zhǔn)系統(tǒng)控件(從UIControl繼承的對(duì)象),但不應(yīng)該以這種方式自定義它們??梢酝ㄟ^控件類本身的明確和詳細(xì)記錄的接口來實(shí)現(xiàn)自定義效果。例如,UIButton類包含設(shè)置按鈕的標(biāo)題和背景圖像的方法。使用標(biāo)準(zhǔn)接口能夠展示正常效果,非常收到會(huì)導(dǎo)致異常。