UILabel的DrawDrect方法
一、问题
如果继承UILabel实现自己的一个Label,并且在子类的DrawRect方法中留空,什么都不写,会发生什么?
代码如下:
VC
@interface ViewController () @property (nonatomic, strong) DrawTestLabel *dwLabel; @end @implementation ViewController - (DrawTestLabel *)dwLabel
{
if(!_dwLabel) {
_dwLabel = [[DrawTestLabel alloc] init];
_dwLabel.textAlignment = NSTextAlignmentCenter;
} return _dwLabel;
} - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[[self view] setBackgroundColor:[UIColor greenColor]];
[[self dwLabel] setFrame:CGRectMake(0, 0, 200, 50)];
[[self view] addSubview:[self dwLabel]];
[[self dwLabel] setText:@"Hello"];
[[self dwLabel] setCenter:[self view].center];
} @end
Label
@implementation DrawTestLabel - (void)drawRect:(CGRect)rect {
// Drawing code
// [super drawRect:rect];
} @end
注释调调用父类的DrawRect方法之后,会发现屏幕上面什么都没有
打开Xcode调试之后,会发现存在一个透明的图层
二、问题分析
我们知道,UIView和Layer的关系,Layer负责画面渲染,UIVIew负责事件响应;
在CALayer中通过实现 CALayerDelegate来实现画面的绘制,通常一个layer的delegate是UIView自身。
CALayerDelegate 的方法 drawlayer:incontext方法在每次绘制的时候,会调用UIView的Drawrect方法,在UIView实现了DrawRect的方法下。
那么上面自己继承的UILbel,重写Drawrect方法之后,大致的逻辑如下
1、CALayer接受到系统的回调,开始渲染
2、系统发现layer(Label)实现了Drawrect方法,那么会创建一个透明的画布,大小是UILabel的发小,scale是屏幕的scale
3、通过delegate调用Drawrect方法,在这个画布之上绘制内容
4、新的UILabel通过TextKit(底层是CoreText)来绘制文字到这个画布之上,这一段是在CPU上完成的
5、绘制完成的bitmap ,再一次Runloop循环中,会通过系统统一提交给后台的renderserver
6、render server进程处理不同的图层,通过操作GPU进行叠加渲染操作
为什么Drawrect消耗比较高?
因为绘制在CPU上面操作
绘制完成的bitmap,会通过跨进城IPC传递给render server存在系统调用消耗
render 传递内存中的bitmap到GPU的缓存上面生成纹理 ,再次产生消耗
普通的UIView通过设置属性的方式,不涉及到传递大块内存的操作,这些类似背景色、透明度、都是通过renderserver来完成的,GPU操作效率会比较高。
UILabel的DrawDrect方法的更多相关文章
- 重写UIlabel的setText:方法,过滤或者拦截text设置
因为项目中很多地方都有对UIlabel的赋值,但是text.length == 0 或者为空时并没有去给默认值,导致很多界面空间是白板, 所以不想一个一个去改.希望能重写UIlabel 的setTex ...
- 获取UILabel宽度的方法
- (CGFloat)labelLength:(NSString *)str font:(CGFloat)font{ str = ISSTRING(str) ? str : @"" ...
- UILabel的使用方法
UILabel 就是一个显示文字的控件,可以设置文字的各种属性. 构造方法: //通过设置Label的边框来初始化UILabel labelOfSlider = [[UILabelal ...
- IOS 学习笔记(4) 控件 标签(UILabel)的使用方法
虽说Label的中文翻译是标签标记,但它其实是一个静态文本内容的展现控件. 一般来说,UILabel只是一个只读的文本视图,开发者可以利用UiLabel来展示内容长度有固定上限的文字内容.并且,UIL ...
- UILabel设定行间距方法
NSString *textStr = @"iPhone规定:任何应用想访问麦克风,必须被授权麦克风服务.请进入"设置"->"隐私"->& ...
- UILabel顶部对齐解决方法(转载)
问题 我有一个UILabel高度最多能显示两行,如果里面内容只有一行,它是垂直居中的.怎么能让它顶端对齐呢? 回答 答案1:用sizeToFit改变UILabel的高度 nevan king,19 ...
- UILabel的顶对齐解决方法
对于有多行文字的UILabel而言,需要设置UILabel的numberoflines属性,此属性默认是1,也就是只显示一行,多余的会以尾部,中间的方式进行截断,具体要看你的初始设置. 在这里可以将其 ...
- IOS UIlabel设置文本距离边框距离
自定义UILabel 继承 UILabel 重写drawTextInRect 方法具体如下: CGRect rect = CGRectMake(rect.origin.x + 5, rect.orig ...
- iOS开发基础控件--UILabel
UILabel 的常见属性和方法: //创建UIlabel对象 UILabel* label = [[UILabel alloc] initWithFrame:self.view.bounds]; / ...
- iOS运用runtime全局修改UILabel的默认字体
iOS运用runtime全局修改UILabel的默认字体 一.需求背景介绍 在项目比较成熟的基础上,遇到了这样一个需求,应用中需要引入新的字体,需要更换所有Label的默认字体,但是同时,对于一些特殊 ...
随机推荐
- c# assembly.GetManifestResourceStream找不到路径
前言 最近发现一个问题,用assembly.GetManifestResourceStream去找资源路径xml的时候,发现找不到,然后有些xml资源又可以找到,这时候有两种思维来思考. 正文 第一种 ...
- 如何解决python安装mysqlclient失败问题
在使用Django等框架来操作MySQL时,实际上底层还是通过Python来操作的,首先需要安装一个驱动程序,在Python3中,驱动程序有多种选择,比如有pymysql以及mysqlclient等. ...
- vue项目node-scss装不上问题( vue执行npm install报错: Can‘t find Python executable “python“, you can set the PYTHON env variable
一.描述从网上下载的一个Vue模板项目,导入VsCode,执行npm install命令后,报错了,报错的信息是node-sass安装失败,同时提示需要python环境的错误信息,这是因为安装node ...
- Redis持久化技术浅析
Redis是一种内存数据库,数据都存储在内存中,因此可以快速地直接基于内存中的数据结构进行高性能的操作,但是所有数据都在内存中,一旦服务器宕机,内存中的数据就会全部丢失,数据将无法恢复,因此Redis ...
- Llama 3 开源了「GitHub 热点速览」
近日,Meta(原 Facebook)开源了他们公司的新一代大模型 Llama 3,虽然目前只放出了 8B 和 70B 两个版本,但是在评估结果上已经优于 Claude 3 Sonnet.Mistra ...
- [PHP] 浅谈 Laravel Scout 的存在意义
注:Laravel Scout 是官方支持的对框架模型数据进行全文检索功能的扩展包. Laravel 的 Scout 与 Eloquent ORM 进行了深度集成,不用开发者再自己进行代码侵入了. L ...
- dotnet OpenXML 利用合并表格单元格在 PPT 文档插入不可见的额外版权信息
本文告诉大家如何利用 Office 对于 OpenXML 支持的特性,在 PPT 的表格里面,通过合并单元格存放一些额外的信息,这些信息对用户来说是不可见的,但是进行拷贝表格等的时候,可以保存此信息内 ...
- 对象存储服务的Lambda特性
AWS S3提供了Lambda服务,详见Amazon S3 Object Lambda. 技术方案 作为兼容AWS S3能力的对象存储服务,交付Lambda特性时,关注点有: 实现方式 SDK 独立进 ...
- rails 上传文件
控制器文件 app/controllers/api/v1/order_controller.rb def create # 从本地读取 log_dir = File.expand_path(File. ...
- Oracle删除列操作:逻辑删除和物理删除
概念 逻辑删除:逻辑删除并不是真正的删除,而是将表中列所对应的状态字段(status)做修改操作,实际上并未删除目标列数据或恢复这些列占用的磁盘空间.比如0是未删除,1是删除.在逻辑上数据是被删除了, ...