原理

深入iOS事件处理层次及原理分析、响应链

2017-10-12  本文已影响79人  找不到工作的iOS

1. iOS事件有哪一些

运动事件

远程控制事件

触摸事件

2. 事件传递和响应

2.1 原理分析

流程.png window流程.png

2.2 HitTest 、pointInside

EOCLightGrayView *grayView = [[EOCLightGrayView alloc] initWithFrame:CGRectMake(50.f, 100.f, 260.f, 200.f)];
    
    redView = [[EOCRedView alloc] initWithFrame:CGRectMake(0.f, 0.f, 120.f, 100.f)];
    
    EOCBlueView *blueView = [[EOCBlueView alloc] initWithFrame:CGRectMake(140.f, 100.f, 100.f, 100.f)];
    
    EOCYellowView *yellowView = [[EOCYellowView alloc] initWithFrame:CGRectMake(50.f, 360.f, 200.f, 200.f)];
    
    [self.view addSubview:grayView];
    [grayView addSubview:redView];
    [grayView addSubview:blueView];
    [self.view addSubview:yellowView];
布局.png 打印.png

2.3 hitTest 内部实现代码还原

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    ///hitTest:判断pointInside,是不是在view里?是的话,遍历,不是的话返回nil;假设我就是点击灰色的,返回的是自己;
    NSLog(@"%s",__func__);
    
    NSArray *subViews = [[self.subviews reverseObjectEnumerator] allObjects];
    UIView *tmpView = nil;
    for (UIView *view in subViews) {
        
        CGPoint convertedPoint = [self convertPoint:point toView:view];
        if ([view pointInside:convertedPoint withEvent:event]) {
            
            tmpView = view;
            break;
            
        }
        
    }
    
    if (tmpView) {
        return tmpView;
    } else if([self pointInside:point withEvent:event]) {
        
        return self;
    } else {
        
        return nil;
        
    }
    
    
    return [self hitTest:point event:event];  //redView
    
    ///这里是hitTest的逻辑
    
    ///alpha(<=0.01)、userInterActionEnabled(NO)、hidden(YES)  pointInside返回的为NO
    
}

2.4 实战之扩大button点击区域

bigbutton.png
@implementation EOCCustomButton

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    NSLog(@"%s", __func__);
   
    //扩大它的响应范围
    CGRect frame = [self getScaleFrame];
    return CGRectContainsPoint(frame, point);
    
   //  return [super pointInside:point withEvent:event];
}

- (CGRect)getScaleFrame {
    
    CGRect rect = self.bounds;
    
    if (rect.size.width < 40.f) {
        rect.origin.x -= (40-rect.size.width)/2;
    }
    
    if (rect.size.height < 40.f) {
        rect.origin.y -= (40-rect.size.height)/2;
    }
    
    rect.size.width = 40.f;
    rect.size.height = 40.f;
    
    return rect;
}

2.5 UIRespond 与 响应链的组成

respondch.png

3. 手势事件

3.1 手势 与 hitTest 的关系

3.2 手势与 触摸事件的关系

3.3 系统如何分辨手势种类

3.4 手势与view的touches事件的关系

下面是系统的默认设置
 tapGesture.delaysTouchesBegan = NO;   
///是否延迟view的touch事件识别;如果延迟了(YES),并且手势也识别到了,touch事件会被抛弃

 tapGesture.cancelsTouchesInView = YES;   
///识别手势之后,是否取消view的touch事件
// 如果为NO, touchesCancelled 不会调用,取而代之的是手势结束后touchesEnd

4. button事件

4.1 系统是如何分辨UIControlEvent

5. 触摸事件的运用

case2.png
上一篇下一篇

猜你喜欢

热点阅读