ios 关于响应链详解

前言:在ios编程中,经常会遇到各种复杂的视图,那么我们点击屏幕,是怎么样将点击事件传递到对应的对象上面,延后完成方法的执行的呢?以下已touch事件为例进行说明:


1.Touch事件的传递顺序:

   在ios编程中,UIResponer负责事件的管理,因此只有UIResponer的子类才能对事件进行处理,UIApplication, UIViewController,和 UIView均是继承自UIResponer。

    

  1. 首先由View尝试处理,不能处理,则传递给Superview
  2. SuperView不能处理,继续传递给SuperView
  3. 因为SuperView是ViewController的根视图,则传递给ViewController
  4. ViewController不能处理,重复1,2,直到到达UIWindow
  5. Window不能处理,传递给UIApplication
  6. 抛弃
2.寻找触摸事件的执行者:

    window对象总会尝试把响应者设为touch产生的view,通过hit-test来判断。Touch事件会沿着第一响应者(Fist Responder)一直传递到UI Application,如果到最后也不能响应,则被抛弃。

    系统如何通过hit-test找到Fist Responder的View 

    举个例子 
    点击如图的viewD 


通过hit-test来判断触摸在那个view的顺序如下

  1. Touch在ViewA的bounds中,递归检查ViewB和ViewC
  2. Touch不在ViewB的bounds中,检查ViewC
  3. Touch在ViewC的bounds中,检查ViewD和ViewE
  4. Touch不在ViewD中,检查ViewE
  5. Touch在ViewE中,所以ViewE为hit-test的结果

每一次hit-test通过两个函数实现。 
调用pointInside:withEvent: 返回改触摸点是否在View中,hitTest:withEvent:返回触摸点所在的View,然后递归检查起subview

所以,可以通过重写pointInside:withEvent来限制一个View的部分区域响应视图,关于这个,举例。


#import "TriangleButton.h"


@interface TriangleButton()


@property (strong,nonatomic)CAShapeLayer * shapeLayer;


@end


@implementation TriangleButton


-(instancetype)initWithFrame:(CGRect)frame{

    if (self = [superinitWithFrame:frame]) {

        [selfsetUp];

    }

    returnself;

}

-(void)setUp{

    self.shapeLayer = [CAShapeLayerlayer];

    CGMutablePathRef path =CGPathCreateMutable();

    CGPathMoveToPoint(path,nil,100,0);

    CGPathAddLineToPoint(path,nil,100,100);

    CGPathAddLineToPoint(path,nil,0,100);

    self.shapeLayer.path = path;

    [self.layersetMask:self.shapeLayer];

    self.layer.masksToBounds =true;

    self.backgroundColor = [UIColoryellowColor];

    

    self.userInteractionEnabled=YES;

    UITapGestureRecognizer *tapClick=[[UITapGestureRecognizeralloc]initWithTarget:selfaction:@selector(tapClick_Click)];

    [selfaddGestureRecognizer:tapClick];

}


-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{

    if (CGPathContainsPoint(self.shapeLayer.path,nil, point, true)) {

        return [superpointInside:point withEvent:event];

    }else{

        returnfalse;

    }

}


-(void)tapClick_Click{

    if (self.buttonClick) {

        self.buttonClick();

    }

}


demo下载地址: https://github.com/changcongcong/TriangleButton


你可能感兴趣的:(ios 关于响应链详解)