美文网首页
iOS 图层知识

iOS 图层知识

作者: 好雨知时节浩宇 | 来源:发表于2017-12-23 15:47 被阅读25次

图层与视图

UIView

在iOS中,所有的视图都是从UIView这个基类派生而来的,UIView可以处理用户触摸事件,可以支持基于Core Graphics绘图,可以支持仿射变换(旋转、缩放等),可以支持类似于滑动、渐变等动画。

CALayer

CALayer在概念上同UIView有些类似,同样也是被层级关系树管理的矩形块,也可以包含一些内容(图片、文字、背景色),也可以管理子图层,有一些方法和属性用来做动画和变换。
和UIView最大的不同是:CALayer不能处理用户的交互。
图层不清楚具体的事件响应链(稍后会有文章详细讲解),因此它不能响应事件。即使它提供了一些判断某个触摸点是否在图层范围内。

平行的层级关系

1、每一个视图都有一个CALayer实例的图层属性,视图的职责就是:创建并管理这个图层,以确保子视图在视图的层级关系中被添加或者移除时,对应的图层在“层级关系树中” 有相同的操作。

图层和视图层平行关系
2、实际上真正在屏幕上显示和做动画的是CALayer图层,UIView 仅仅是对CALayer的封装,提供了一些iOS类似处理触摸等事件的功能,以及Core Animation底层方法的高级接口。
3、既然说CALayer是UIView内部的实现细节,那我们是否没有必要理解它?
某种意义上讲的确是这样的,对于一些简单的需求来说,我们确实没有必要处理CALayer,通过UIView提供的API即可完成,假如我们需要从底层上做一些改变,那么我们只能选择去了解CALayer.

UIView没有暴露出来的CALayer功能:
1、阴影、圆角、带颜色的边框
2、3D变换
3、非矩形范围
4、透明遮罩
5、多级非线性动画

那为什么要基于UIView和CALayer提供两个平行的层级关系?

职责分离-

CALayer 、UIView的继承关系:

1、CALayer直接继承于NSObject
2、UIView继承于UIResponder类,UIResponder中定义了处理各种事件和事件传递的接口。


继承关系图.png

UIView创建流程(UIView、CALayer的组合关系)

1、先说一下UIView创建过程:当我们实例化一个view时,UIView执行了initWithFrame:后,内部会调用私有方法_createLayerWithFrame:来创建CALayer图层。
下面是获取到的调用栈:

截图1.png

注:这里我们重写了view的类方法:layerClass,使其返回我们自定义的CALayer。

2、之后我们看到系统会去调用CALayer的setFrame:、setPosition:、setBounds:去设置图层最终的frame
调用栈如下:

屏幕快照 2017-12-22 下午5.52.57.png

也就是说:我们在创建view时设置的frame,最终转化成了给view的layer设置frame和position。

我们总结下调用过程如下:

[UIView _createLayerWithFrame]
[Layer setBounds:bounds]
[Layer setFrame:Frame]
[Layer setPosition:position]
[Layer setBounds:bounds]

同理,我们可以理解UIView的frame 获取其实是对CALayer frame的简单封装而已。本质返回的还是CALayer的frame值。

3、上面是布局,接下来要进行绘制,我们看到 UIView调用drawRect:进行绘图的操作,实际上是由CALayer通过CALayerDelegate在代理方法内部调用的drawRect: ,说明真正的内容绘制操作还是由CALayer来负责。
调用栈如下:

屏幕快照 2018-07-01 17.54.30.png

简单分析下:
当UIView需要绘制显示时,它内部的层会准备好一个CGContextRef(图形上下文),然后调用delegate(这里就是UIView)的drawLayer:inContext:方法,并且传入已经准备好的CGContextRef对象。而UIView在drawLayer:inContext:这个代理方法中又会调用自己的drawRect:方法。
这里引出一个CGContextRef获取的问题,有过经验的开发都知道:

当我们通过core Graphic绘图时, 在使用UIGraphicsGetCurrentContext()时,只有在drawRect:中获取上下文才是有效的。而在其他地方获取是nil。
原因:系统会维护一个CGContextRef的栈,UIGraphicsGetCurrentContext()会取出栈顶的context,只有Layer调用了它的代理方法时(也就是上面的drawLayer:inContext:),才会往栈中压入一个有效的CGContextRef。
到这里是不是就清楚了之前为什么不能再其他地方获取这个context。

在drawRect中完成的绘制,也会被填入到context中,然后被提交到系统的transition队列中等待渲染,最后展示在屏幕上。

基于第三点我们可以简单的认为:CALaye 侧重内容的绘制,而UIView 侧重内容的管理和组建

4、在做 iOS 动画的时候,修改非 RootLayer的属性(譬如位置、背景色等)会默认产生隐式动画,而修改UIView则不会。

总结:1、2 步是View布局的过程,3是绘制的过程。
我们在通过代码创建了一个view后,这个view最终展示在屏幕上会有两个过程:
1、布局,也就是给view设置frame,bounds,border等 参数 ,但是这时仅仅是设置参数而已。通常这一步对应LayoutView 等函数。
2、上一步设置完参数,需要根据设置好的参数,把view绘制出来。这一步对应drawRect:函数。

续:
在验证过程中,重写了layer,这里顺道也添加上,方便大家指正问题。

@implementation CustomView
- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];
}
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
    //这个函数对外没有公开,是UIView内部实现的代理类,我们重写该函数可以确认,UIView确实是CALayer的代理
}
+ (Class)layerClass {
    return [HYLayer class];
}
@end


@implementation HYLayer

- (void)setFrame:(CGRect)frame {
    [super setFrame:frame];
}
- (void)setBounds:(CGRect)bounds {
    [super setBounds:bounds];
}
- (void)setPosition:(CGPoint)position {
    [super setPosition:position];
}
- (void)display {
    [super display];
}
- (void)drawInContext:(CGContextRef)ctx {
    [super drawInContext:ctx];
    
}
@end

相关文章

  • iOS 图层知识

    图层与视图 UIView 在iOS中,所有的视图都是从UIView这个基类派生而来的,UIView可以处理用户触摸...

  • 图层知识,图层相关实用知识

    PS这个软件我从大学时期就开始用,经历了这么多版本,看着它从7.0走到现在,一路摸爬滚打,今天就分享一下PS中,关...

  • iOS CALayer (图层的相关知识)

    CALayer简介 在iOS中,你能看得见摸得着的东西基本上都是UIView,比如一个按钮、一个文本标签、一个文本...

  • UITableView视图层级的变化

    UITableView视图层级的变化 iOS7 UITableView的视图层级变化 在iOS的开发过程中,我们经...

  • iOS图层

    CAShapeLayer通过矢量图形而不是位图(bitmap)来绘制的图层子类。可以绘制所有通过CGPath来表示...

  • iOS图层树理解

    iOS图层树(图层的树状结构) CoreAnimation 屏幕上不同的可视内容(可分解成各个独立的图层)通过Co...

  • 干货|CAD系列教程 --- 图层

    图层 一、图层的概念。 图层是auto cad核心知识点,设计师必掌握的知识。用简单直白的语言来形容下,每...

  • iOS动画事物(CATransaction)

    动画事物 CATransaction是 Core Animation 中的事务类,在iOS中的图层中,图层的每个改...

  • ios11前修改系统自带的滑动删除按钮

    ios11前是可以在系统图层上修改删除按钮的,这个图层叫UITableViewCellDeleteConfirma...

  • Core Animation系列之CATransaction

    CATransaction是 Core Animation 中的事务类,在iOS中的图层中,图层的每个改变都是事务...

网友评论

      本文标题:iOS 图层知识

      本文链接:https://www.haomeiwen.com/subject/hxvpwxtx.html