Texture 性能優(yōu)化

這是 Texture 文檔系列翻譯迷捧,其中結(jié)合了自己的理解和工作中的使用體會。如果哪里有誤,希望指出朴译。

  1. Texture 核心概念

  2. Texture 布局 Layout

  3. Texture 便捷方法

  4. Texture 性能優(yōu)化

  5. Texture 容器 Node Containers

  6. Texture 基本控件 Node

  7. Texture 中 Node 的生命周期

Layer Backing

通過使用 layer 而非 view 可以顯著提高 app 性能蟆融,推薦在不需要觸摸事件的 node 中開啟 layer-backing草巡。

UIKit中,手動將基于視圖的代碼轉(zhuǎn)換為 layer 很費力型酥,并且在需要啟用觸摸處理或其他特定于視圖的功能時山憨,需要手動將所有內(nèi)容轉(zhuǎn)換回去查乒。

在 Texture 中,將 node 的視圖及所有 subtree 轉(zhuǎn)換為 layer 非常簡單:

rootNode.isLayerBacked = YES;

需要轉(zhuǎn)換回 view 時郁竟,只需刪除這一行玛迄。

子樹柵格化 Subtree Rasterization

將整個視圖層級合成為一個圖層可以提高性能,但在UIKit中會影響可維護(hù)性和基于層級結(jié)構(gòu)的推理棚亩。

在 node 中蓖议,開啟合成非常簡單:

[rootNode enableSubtreeRasterization];

上述代碼使從 rootNode 開始整個 node 層次結(jié)構(gòu)合成為一層。

同步并發(fā) Synchronous Concurrency

ASViewControllerASCellNode都有一個布爾類型neverShowPlaceholders屬性蔑舞。通過將此屬性設(shè)置為YES拒担,cell 或視圖控制器的 view 繪制完成前主線程將被堵塞。

開啟該屬性后攻询,并不能充分利用 Texture 的性能从撼。通常 node 已被預(yù)加載,在進(jìn)入屏幕時即將完成钧栖,因此堵塞時間很短低零。即使rangeTuningParameters設(shè)置為0,Texture 性能也優(yōu)于UIKit拯杠。因為即使主線程堵塞掏婶,subnode 也在并發(fā)執(zhí)行。

查看NSSpain 2015 talk video了解其具體行為:

node.neverShowPlaceholders = YES;

通常潭陪,cell 繪制完成前進(jìn)入了屏幕會顯示占位符雄妥,直到繪制完成。將neverShowPlaceholders設(shè)置為YES使 Texture 更像UIKit依溯,即滑動時會像UIKit一樣掉幀老厌,盡管 Texture 速度會快些。

TextureSynchronousConcurrency.jpg

圓角 Corner Rounding

對于圓角處理黎炉,很多開發(fā)人員都會選擇CALayercornerRadius屬性枝秤。但cornerRadius會嚴(yán)重影響性能,應(yīng)在沒有其他選擇時才使用慷嗜。這一部分將涵蓋:

  • 為何不應(yīng)使用CALayercornerRadius淀弹。
  • 其他更為高效實現(xiàn)圓角方式,以及何時使用庆械。
  • 選擇圓角處理的流程圖薇溃。
  • Texture 實現(xiàn)圓角的方法。

CALayer 的 cornerRadius 耗費性能

使用CALayercornerRadius會觸發(fā)離屏渲染(offscreen rendering)缭乘,以在每幀上執(zhí)行裁剪操作痊焊。滾動時每秒需要在60幀上執(zhí)行裁剪操作,即使內(nèi)容沒有發(fā)生任何變化。這意味著 GPU 必須在每幀之間切換上下文薄啥,包括合成整個幀和裁剪辕羽。

這些對性能的消耗不會顯示在 Time Profiler 中,因為其影響的是 CoreAnimation Render Server垄惧,會造成掉幀刁愿。

圓角策略

當(dāng)選擇圓角策略時,只需考慮以下三點:

  1. 圓角下(movement underneath the corner)是否有滑動到逊。
  2. 是否有穿過圓角滑動(movement through the corner)铣口。
  3. 四個圓角是否處于同一個 node 上,有沒有與其他 node 相交觉壶。

圓角下滑動是指圓角后面的任何運動脑题。例如,當(dāng)一個圓角 cell 在背景上滾動時铜靶,背景就是在圓角下滑動叔遂。

為了描述穿過圓角滑動,可以想象一個小的圓角滾動視圖争剿,其中包含大很多的圖片已艰。當(dāng)在滾動視圖內(nèi)縮放、平移圖片時蚕苇,照片將在滾動視圖的各個角中穿過哩掺。

Texturecorner-rounding-movement.png

上圖中,藍(lán)色表示圓角下有滑動涩笤;橙色表示穿過圓角滑動嚼吞。

圓角對象內(nèi)部有移動,而無需移過角蹬碧。下圖顯示了以綠色標(biāo)志的內(nèi)容舱禽,該內(nèi)容從邊緣開始插入,其邊距等于圓半徑大小锰茉。當(dāng)內(nèi)容滾動時,它不會在角落滾動切心。

Texturecorner-rounding-scrolling.png

使用上述方法來調(diào)整設(shè)計以消除圓角移動的影響飒筑,以便不影響性能的情況下使用cornerRadius

最后需要注意是否四個角處于同一個 node 中绽昏,或 subnode 與圓角相交协屡。

Texturecorner-rounding-overlap.png

預(yù)合成角 Precomposited Corners

預(yù)合成角指使用貝塞爾曲線繪制角的曲線,以在 CGContext / UIGraphicsContext 中剪切內(nèi)容全谤。在這種情況下肤晓,拐角將成為圖像本身的一部分,并被同步到CALayer中,有兩種類型的預(yù)合成角:

最佳方案為使用預(yù)合成的不透明角(precomposited opaque corner)补憾,這是最高效的方法漫萄,可實現(xiàn)零 alpha 混合(盡管這比避免觸發(fā)屏外渲染的重要性小很多),但其不夠靈活盈匾。如果圓角的對象需要移動腾务,則后面的背景將需要為純色。使用 Texture 或圖片背景會很棘手削饵,推薦使用預(yù)合成的 alpha 角岩瘦。

第二種涉及貝塞爾曲線的角是預(yù)合成 alpha 角(precomposited alpha corner),此方法非常靈活窿撬,是最常用的方法之一启昧。其會增加在這個內(nèi)容上進(jìn)行 alpha 混合的成本,并且 alpha 通道不透明會增加25%內(nèi)存消耗劈伴,但這些消耗對于現(xiàn)代設(shè)備來說很小密末,與cornerRadius觸發(fā)的離屏渲染不在同一數(shù)量級。

預(yù)合成角要求角必須在同一 node宰啦,且不與 subnode 相交苏遥。不滿足任一條件,則需使用裁剪圓角赡模。

當(dāng)使用了shouldRasterizeDescendants后田炭,Texture 會自動對cornerRadius進(jìn)行預(yù)合成。在開啟柵格化前漓柑,請務(wù)必仔細(xì)考慮教硫,具體可以查看子樹柵格化 Subtree Rasterization

Texture 的UIImage+ASConveniences.h提供了簡單、純色圓角實現(xiàn)方法辆布,支持 alpha 和不透明創(chuàng)建平面顏色瞬矩,圓角可以調(diào)整大小,非常適合于圖像 node 和ASButtonNode的背景占位符锋玲。

剪裁圓角 Clip Corner

Clip corner 通過向四個角放置四個不透明內(nèi)容實現(xiàn)圓角景用。這種方法靈活、性能高惭蹂。四個單獨 layer 對于 CPU 來說性能消耗很少伞插。

Textureclip-corners.png

Clip Corner 適用于以下兩種情況:

  • 四個角在不同 node,或與 subnode 相交盾碗。
  • 圓角只在 node 頂部媚污。

是否可以使用CALayer的cornerRadius

雖然很少、但也存在必須使用cornerRadius的情況廷雅。例如耗美,在實現(xiàn)動畫時京髓,圓角下滑動、穿過圓角的內(nèi)容是動態(tài)的商架,但通逞咴梗可以通過改變設(shè)計利用前面的解決方案。

屏幕沒有任何滑動時甸私,使用cornerRadius對性能的影響小很多诚些。只要屏幕有滑動,即使不涉及圓角部分皇型,也會因使用cornerRadius對性能產(chǎn)生影響诬烹。例如,導(dǎo)航欄中有一個圓形元素弃鸦,其下方有滾動視圖绞吁,即使它們不重疊,也會產(chǎn)生影響唬格〖移疲滑動屏幕上任何內(nèi)容,均會對性能產(chǎn)生影響购岗,即使用戶沒有與其交互汰聋。此外,任何類型的屏幕刷新喊积,都將因cornerRadius而產(chǎn)生額外開銷烹困。

Rasterization 和 Layerbacking

雖然使用CALayershouldRasterize可以提高cornerRadius的性能,但這是一個未充分理解的選項乾吻,通常很危險髓梅。在無需重新柵格化時(即沒有滑動、點擊更改顏色绎签,也不在移動的表視圖上)枯饿,可以使用shouldRasterize屬性。通常诡必,不建議使用shouldRasterize奢方,其可能會導(dǎo)致更為嚴(yán)重的性能下降。對于本身性能不佳爸舒、堅持使用cornerRadius屬性的app來說蟋字,其能夠帶來一定的性能提升。但如果正從零構(gòu)建一款 app碳抄,強烈建議選擇前面更好的圓角策略愉老。

CALayershouldRasterize與 Texture 的node.shouldRasterizeDescendents無關(guān)场绿,當(dāng)開啟shouldRasterizeDescendents后剖效,將阻止 subnode 創(chuàng)建 view 和 layer嫉入。

圓角策略選取

使用下面流程圖選取合適圓角策略:

Texturecorner-rounding-flowchart-v2.png

Texture 實現(xiàn)圓角的方式

在 Texture 中,有以下幾種實現(xiàn)圓角的方式璧尸。

使用 cornerRadius
CGFloat cornerRadius = 20.0;
    
_photoImageNode.cornerRoundingType = ASCornerRoundingTypeDefaultSlowCALayer;
_photoImageNode.cornerRadius = cornerRadius;
使用 precomposition
CGFloat cornerRadius = 20.0;
    
_photoImageNode.cornerRoundingType = ASCornerRoundingTypePrecomposited;
_photoImageNode.cornerRadius = cornerRadius;

使用 clipping

CGFloat cornerRadius = 20.0;

_photoImageNode.cornerRoundingType = ASCornerRoundingTypeClipping;
_photoImageNode.backgroundColor = [UIColor whiteColor];
_photoImageNode.cornerRadius = cornerRadius;
使用 willDisplayNodeContentWithRenderingContext 設(shè)置裁剪路徑
CGFloat cornerRadius = 20.0;
    
// Use the screen scale for corner radius to respect content scale
CGFloat screenScale = UIScreen.mainScreen.scale;
_photoImageNode.willDisplayNodeContentWithRenderingContext = ^(CGContextRef context, id drawParameters) {
    CGRect bounds = CGContextGetClipBoundingBox(context);
    CGFloat radius = cornerRadius * screenScale; 
    UIImage *overlay = [UIImage as_resizableRoundedImageWithCornerRadius:radius
                                                             cornerColor:[UIColor clearColor]
                                                               fillColor:[UIColor clearColor]];
    [overlay drawInRect:bounds];
    [[UIBezierPath bezierPathWithRoundedRect:bounds cornerRadius:radius] addClip];
};
使用 ASImageNode 獲取圓形圖像并添加邊框

非常適合于獲取圓形頭像咒林。

CGFloat cornerRadius = 20.0;

_photoImageNode.imageModificationBlock = ASImageNodeRoundBorderModificationBlock(5.0, [UIColor orangeColor]);

上一篇:Texture 便捷方法

下一篇:Texture 容器 Node Containers

歡迎更多指正:https://github.com/pro648/tips

本文地址:https://github.com/pro648/tips/blob/master/sources/Texture%20%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96.md

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市爷光,隨后出現(xiàn)的幾起案子垫竞,更是在濱河造成了極大的恐慌,老刑警劉巖蛀序,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件欢瞪,死亡現(xiàn)場離奇詭異,居然都是意外死亡徐裸,警方通過查閱死者的電腦和手機遣鼓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來重贺,“玉大人骑祟,你說我怎么就攤上這事∑希” “怎么了次企?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長潜圃。 經(jīng)常有香客問我缸棵,道長,這世上最難降的妖魔是什么秉犹? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任蛉谜,我火速辦了婚禮,結(jié)果婚禮上崇堵,老公的妹妹穿的比我還像新娘型诚。我一直安慰自己,他們只是感情好鸳劳,可當(dāng)我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布狰贯。 她就那樣靜靜地躺著,像睡著了一般赏廓。 火紅的嫁衣襯著肌膚如雪涵紊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天幔摸,我揣著相機與錄音摸柄,去河邊找鬼。 笑死既忆,一個胖子當(dāng)著我的面吹牛驱负,可吹牛的內(nèi)容都是我干的嗦玖。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼跃脊,長吁一口氣:“原來是場噩夢啊……” “哼宇挫!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起酪术,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤器瘪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后绘雁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體橡疼,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年庐舟,在試婚紗的時候發(fā)現(xiàn)自己被綠了衰齐。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡继阻,死狀恐怖耻涛,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情瘟檩,我是刑警寧澤抹缕,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站墨辛,受9級特大地震影響卓研,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜睹簇,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一奏赘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧太惠,春花似錦磨淌、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至埃脏,卻和暖如春搪锣,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背彩掐。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工构舟, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人堵幽。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓狗超,卻偏偏與公主長得像监嗜,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子抡谐,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,592評論 2 353

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