前言
对于优化的必要行和优化的可行性,App 渲染性能优化是一个普遍存在的问题。页面卡顿,手机耗电等问题渲染的优惠都能解决或者减轻 问题造成的影响。
app 性能 是个相比渲染更大的命题,渲染的优化是性能优化很重要的一部分。
阻塞主线程的任务,主要分为上面这三大类。文本和布局的计算、渲染、解码、绘制都可以通过各种方式异步执行,但 UIKit 和 Core Animation 相关操作必需在主线程进行。
具体方法和途径
其中之一 同步渲染排版
在图文混排的情况下,解决方案 实践得出的一个方案
可能不是最优,但是 代码量和实践复杂度是最小
如一个 Controller 中添加一个view, viewdidload 在整体绘制之前,我们要得到所有图片在CTFrame中位置
编排一个 自己的class 对于绘制的Data 进行进一步封装
CoreTextData *data = [[CoreTextData alloc] init];
data.ctFrame = frame; //CTFrame
data.height = textHeight;
这个是核心,核心的表现是,Frame 和Height 这两个属性 一旦确定,对于上下文的Context 就有自己的归宿。CGContext 为CoreGraphic 库Class ,虽然CoreText 为了文案 的绘制提供了便利,但是,还是要借助CoreGraphic对图片进行绘制,和必要条件的获取。
起步开始-我的Attribute
在这之前,要做的事情:
text 直接变成 attributeString
image 记录下name & 位置 将image 也变成 attributeString(其实是为了占位)
这样 产生的 NSAttributedString 是全部的了
重点的CGFrame
绘制区域是最为困难想明白的部分,CoreText 对于不常用的API 集合 Frame 的获取有很多方式,最常用的方式
- 通过
- 通过CTFramesetterRef CTFramesetterCreateWithAttributedString 方法 开始使用 attributeString 对象. ->生成 CTFramesetterRef 对象
- 利用 CTFramesetterRef 对象 获得要绘制的区域的高度(宽度是自己定)获取 width / height
- 一切为了 CTFrameRef 对象的生成服务
// 1.有了width / height 配置 对应的CGMutablePathRef path 对象
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, CGRectMake(0, 0, config.width, height));
CTFrameRef 对象生成 用到上文 费了半天功夫来配置出来的path
( CTFramesetterRef 对象 根据 attributeString 来的)
CTFrameRef CTFramesetterCreateFrame(
CTFramesetterRef framesetter,
CFRange stringRange,
CGPathRef path,
CFDictionaryRef _Nullable frameAttributes )
提示: CGPathRef参数 根据Height->也是attributeString ; CTFramesetterRef 对象也是根据 attributeString 获得
最后的Draw InView
Draw 在view 里面 通过自己的编排生成的 CoreTextData 对象,来CTFrameDraw 画到view 上。
在custom view 里面的draw 方法
CustomView.m
- (void)drawRect:(CGRect)rect{
}
CGContextRef context = UIGraphicsGetCurrentContext();//1.获取当前绘图上下文
CGContextSetTextMatrix(context, CGAffineTransformIdentity);//2
CGContextTranslateCTM(context, 0, self.bounds.size.height);//2
CGContextScaleCTM(context, 1.0, -1.0); //2.旋转坐坐标系(默认和UIKit坐标是相反的)
draw //3 绘制
4.1 draw 普通文本
CTFrameDraw(self.data.ctFrame, context); //文字绘画
这个可以扩展 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];
重点在队列的-异步排版
阻塞主线程的任务,主要分为上面这三大类。文本和布局的计算、渲染、解码、绘制都可以通过各种方式异步执行,但 UIKit 和 Core Animation 相关操作必需在主线程进行。
异步排版-目前看到的异步排版 一般是在 Draw 的时候,对于Draw 方式很多,CoreText 提供丰富的Draw 方式
CTLineDraw
RunDraw
FrameDraw 等等 衍生的API
数据
难点
异步排版的队列控制 -线程安全 就是一个实现方法很多的命题
如何优雅的获取AttributeString ,对于纯文本还好,但是对于图文,可能获取的时候,图片的占位 要有自己的设计结构 (优雅的布局框架)
数据监听,工具选择 和 内存监听实时
网络参考资料匮乏,大部分都是老资料,新款iPhone 和新系统的进一步优化方案FrameWork 资料匮乏
总结
总结: 都是 AttributeString 文字 用CoreText 图片 用 CoreGraphics