UIView和CALayer

1. UIView和CALayer

结构图
  • CALayer负责显示内容contents
  • UIView为CALayer提供现实的内容,以及负责处理触摸事件,参与响应链

UIView和CALayer的这种设计模式,体现了六大设计原则中的——单一职能原则。即一个类只负责一件事情。

2. 事件传递与传递链

1

问:点击View C2,系统是如何找到响应的视图View C2,事件是如何传递的?

2.1 事件传递用到的两个主要的方法

方法1:返回的是UIView,如果某个视图能响应事件,就返回这个视图
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;


方法2:返回的是BOOL值,判断某一个点击的位置(CGPoint),是否在当前视图内,如果是,返回YES
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;

2.2 传递链,点击屏幕寻找第一响应者的流程

流程图

2.3 hitTest内部实现

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;

  1. 检查该视图是否被隐藏,是否可交互,透明值是否大于0.01,如果有一项满足,则返回 nil
  2. 利用方法- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event; 检查点击的点是否在当前视图内部,如果不在,则返回 nil
  3. 倒序遍历自己的子视图(后加入的子视图先遍历),每个子视图都调用一次- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;,如果某个子视图返回了一个UIView,则可以return这个view
  4. 如果所有子视图都返回nil,则把自己返回


    hitTest

3. 响应链

事件虽然通过传递链从上到下找到了第一响应者,但是第一响应者不一定能处理这个事件,事件最后由谁来处理,还需要通过一个从下往上的响应链来寻找

响应链
  • 响应链的流程如上图所示,从UIView → UIView的父视图 → UIViewController → UIWindow → UIApplication → UIApplicationDelegate

3.1 几个方法

- (void)touchesBegin:(NSSet *)touches withEvent:(UIEvent *)event;

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;

3.2 事件的传递

事件的传递
  • 如上图所示,如果点击圆圈地方,C2不能处理,则会交给B2(C2的父视图)处理,如果B2也不能处理,则传递给A(B2的父视图)处理,如果A也不能处理,则会沿着A → UIViewController → UIWindow → UIApplication → UIApplicationDelegate一直向上传递
  • 如果当UIApplicationDelegate都不处理这个事件,则这个事件会被丢弃,什么事都不会发生

你可能感兴趣的:(UIView和CALayer)