App 面向UI編程

image-20190324231208978.png

前言

對于優(yōu)化的必要行和優(yōu)化的可行性,App 渲染性能優(yōu)化是一個普遍存在的問題。頁面卡頓,手機(jī)耗電等問題渲染的優(yōu)惠都能解決或者減輕 問題造成的影響。

app 性能 是個相比渲染更大的命題,渲染的優(yōu)化是性能優(yōu)化很重要的一部分。

阻塞主線程的任務(wù),主要分為上面這三大類。文本和布局的計(jì)算、渲染、解碼、繪制都可以通過各種方式異步執(zhí)行,但 UIKit 和 Core Animation 相關(guān)操作必需在主線程進(jìn)行。

具體方法和途徑

其中之一 同步渲染排版

在圖文混排的情況下,解決方案 實(shí)踐得出的一個方案

可能不是最優(yōu),但是 代碼量和實(shí)踐復(fù)雜度是最小

如一個 Controller 中添加一個view, viewdidload 在整體繪制之前,我們要得到所有圖片在CTFrame中位置

編排一個 自己的class 對于繪制的Data 進(jìn)行進(jìn)一步封裝

CoreTextData *data = [[CoreTextData alloc] init];
data.ctFrame = frame; //CTFrame
data.height = textHeight;

這個是核心,核心的表現(xiàn)是,F(xiàn)rame 和Height 這兩個屬性 一旦確定,對于上下文的Context 就有自己的歸宿。CGContext 為CoreGraphic 庫Class ,雖然CoreText 為了文案 的繪制提供了便利,但是,還是要借助CoreGraphic對圖片進(jìn)行繪制,和必要條件的獲取。

起步開始-我的Attribute

在這之前,要做的事情:

  1. text 直接變成 attributeString

  2. image 記錄下name & 位置 將image 也變成 attributeString(其實(shí)是為了占位)

這樣 產(chǎn)生的 NSAttributedString 是全部的了

重點(diǎn)的CGFrame

繪制區(qū)域是最為困難想明白的部分,CoreText 對于不常用的API 集合 Frame 的獲取有很多方式,最常用的方式

  1. 通過
    1. 通過CTFramesetterRef CTFramesetterCreateWithAttributedString 方法 開始使用 attributeString 對象. ->生成 CTFramesetterRef 對象
    2. 利用 CTFramesetterRef 對象 獲得要繪制的區(qū)域的高度(寬度是自己定)獲取 width / height
    3. 一切為了 CTFrameRef 對象的生成服務(wù)

? // 1.有了width / height 配置 對應(yīng)的CGMutablePathRef path 對象

 CGMutablePathRef path = CGPathCreateMutable();
 CGPathAddRect(path, NULL, CGRectMake(0, 0, config.width, height));
    
CTFrameRef  對象生成 用到上文 費(fèi)了半天功夫來配置出來的path 

? ( CTFramesetterRef 對象 根據(jù) attributeString 來的)

CTFrameRef CTFramesetterCreateFrame(
    CTFramesetterRef framesetter,
    CFRange stringRange,
    CGPathRef path,
    CFDictionaryRef _Nullable frameAttributes )

提示: CGPathRef參數(shù) 根據(jù)Height->也是attributeString ; CTFramesetterRef 對象也是根據(jù) attributeString 獲得

最后的Draw InView

Draw 在view 里面 通過自己的編排生成的 CoreTextData 對象,來CTFrameDraw 畫到view 上。

在custom view 里面的draw 方法

CustomView.m 
- (void)drawRect:(CGRect)rect{
  
}
  
 CGContextRef context = UIGraphicsGetCurrentContext();//1.獲取當(dāng)前繪圖上下文
 CGContextSetTextMatrix(context, CGAffineTransformIdentity);//2
 CGContextTranslateCTM(context, 0, self.bounds.size.height);//2
 CGContextScaleCTM(context, 1.0, -1.0); //2.旋轉(zhuǎn)坐坐標(biāo)系(默認(rèn)和UIKit坐標(biāo)是相反的)

 draw //3 繪制

4.1 draw 普通文本

CTFrameDraw(self.data.ctFrame, context); //文字繪畫

這個可以擴(kuò)展 CTLineDraw / CTRunDraw

4.2 draw 圖片
CG_EXTERN void CGContextDrawImage(
CGContextRef cg_nullable c,
CGRect rect,
CGImageRef cg_nullable image)

提示1 上下文 2 圖片位置 3 圖片(UIImage image = [UIImage imageNamed:imageData.name];

重點(diǎn)在隊(duì)列的-異步排版

阻塞主線程的任務(wù),主要分為上面這三大類。文本和布局的計(jì)算、渲染、解碼、繪制都可以通過各種方式異步執(zhí)行,但 UIKit 和 Core Animation 相關(guān)操作必需在主線程進(jìn)行。

異步排版-目前看到的異步排版 一般是在 Draw 的時(shí)候,對于Draw 方式很多,CoreText 提供豐富的Draw 方式

CTLineDraw

RunDraw

FrameDraw 等等 衍生的API

數(shù)據(jù)

難點(diǎn)

  1. 異步排版的隊(duì)列控制 -線程安全 就是一個實(shí)現(xiàn)方法很多的命題

  2. 如何優(yōu)雅的獲取AttributeString ,對于純文本還好,但是對于圖文,可能獲取的時(shí)候,圖片的占位 要有自己的設(shè)計(jì)結(jié)構(gòu) (優(yōu)雅的布局框架)

  3. 數(shù)據(jù)監(jiān)聽,工具選擇 和 內(nèi)存監(jiān)聽實(shí)時(shí)

  4. 網(wǎng)絡(luò)參考資料匱乏,大部分都是老資料,新款iPhone 和新系統(tǒng)的進(jìn)一步優(yōu)化方案FrameWork 資料匱乏

總結(jié)

總結(jié): 都是 AttributeString 文字 用CoreText 圖片 用 CoreGraphics

資料參考

基礎(chǔ)知識

基礎(chǔ)知識_2

基礎(chǔ)知識_3

開源demo

開源demo2

性能測試demo

實(shí)踐優(yōu)化

Graver 美團(tuán)排版

TextKit wwdc

頁面流暢的技術(shù)點(diǎn)

Texture

https://my.oschina.net/FEEDFACF/blog/1858441

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容