
前言
對于優(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
在這之前,要做的事情:
text 直接變成 attributeString
image 記錄下name & 位置 將image 也變成 attributeString(其實(shí)是為了占位)
這樣 產(chǎn)生的 NSAttributedString 是全部的了
重點(diǎn)的CGFrame
繪制區(qū)域是最為困難想明白的部分,CoreText 對于不常用的API 集合 Frame 的獲取有很多方式,最常用的方式
- 通過
- 通過CTFramesetterRef CTFramesetterCreateWithAttributedString 方法 開始使用 attributeString 對象. ->生成 CTFramesetterRef 對象
- 利用 CTFramesetterRef 對象 獲得要繪制的區(qū)域的高度(寬度是自己定)獲取 width / height
- 一切為了 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)
異步排版的隊(duì)列控制 -線程安全 就是一個實(shí)現(xiàn)方法很多的命題
如何優(yōu)雅的獲取AttributeString ,對于純文本還好,但是對于圖文,可能獲取的時(shí)候,圖片的占位 要有自己的設(shè)計(jì)結(jié)構(gòu) (優(yōu)雅的布局框架)
數(shù)據(jù)監(jiān)聽,工具選擇 和 內(nèi)存監(jiān)聽實(shí)時(shí)
網(wǎng)絡(luò)參考資料匱乏,大部分都是老資料,新款iPhone 和新系統(tǒng)的進(jìn)一步優(yōu)化方案FrameWork 資料匱乏
總結(jié)
總結(jié): 都是 AttributeString 文字 用CoreText 圖片 用 CoreGraphics