5、触摸事件

概念

UIEvent:

表示一个触摸事件(从第一个手指开始触摸屏幕到最后一个手指离开屏幕)一个UIevent包括多个UITouch对象组成,有几根手指就有几个touch对象。

属性:UIEventType

UIEventTypeTouches,//触摸
UIEventTypeMotion,//移动
UIEventTypeRemoteControl,//远程控制
UIEventTypePresses NS_ENUM_AVAILABLE_IOS(9_0),//有力度的按压

属性:allTouchs,表示所有UITouch的对象集合

UITouch

表示一个根手指的点击事件,能够表明当前手指的点击位置,状态(触碰,移动,离开)

- (CGPoint)locationInView:(nullable UIView *)view;//获取当前点击的点在view中坐标
- (CGPoint)previousLocationInView:(nullable UIView *)view//获取上个点击的点在view中坐标

UIResponder

在iOS中能够相应事件的对象都是UIResponder子类对象。UIResponder提供了四个供用户点击回调的方法(开始、移动、结束、取消),其中只有当程序强制退出、来电等意外情况中断时才对调用“取消”事件。

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesEstimatedPropertiesUpdated:(NSSet<UITouch *> *)touches NS_AVAILABLE_IOS(9_1);

可以在UIResponder中重写上述方法来进行点击回调监听。

当多个视图叠加,手势又互有冲突时怎么判断哪个View处理哪个时间呢?

现在涉及到响应链的生成与处理。

响应链

响应链是由当前视图所有可以执行或响应触摸事件的UIResponder组成,是一个树形结构

  • 响应链的形成:appdelegate->UIApplication–>UIWindow–>RootViewController–>RootViewController.view ……
  • 响应事件的分发,从第一个UIWindow对象开始,先判断UIWindow是否合格,其次判断 点击位置在不在这个Window内,如果不在 ,返回nil, 就换下一个UIWindow;如果在的话,并且UIWindow没有subView就返回自己,整个过程结束。如果UIWindow有subViews,就从后往前遍历整个subViews,做和UIWindow类似的事情,直到找到一个View。如果没有找到到就不做传递。(合格的意思是:控件允许接收时间,1、不能被隐藏 2、alpha的值大于0.01 3、isUserInterface为YES,UILabel和UIImageView 默认是NO)
  • 响应事件的判断:通过分发找到的view在调用- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;来判断是否由哪个view处理。
//模拟系统判断
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event {
  //判断是否合格
    if (!self.hidden && self.alpha > 0.01 && self.isUserInteractionEnabled) {
        //判断点击位置是否在自己区域内部
        if ([self pointInside: point withEvent:event]) {
            UIView *attachedView;
            for (int i = self.subviews.count - 1; i >= 0; i--) {
                UIView *view  = self.subviews[i];
                //对子view进行hitTest
                attachedView =  [view hitTest:point withEvent:event];
                if (attachedView)
                    break;
            }
            if (attachedView)  {
                return attachedView;
            } else {
                return self;
            }
        }
    }
    returnnil;
}

更好的文章 http://www.jianshu.com/p/cb0314b72883

-原文链接-

6、iOS 11镜像文件

iOS11真机调试,镜像文件下载
链接: https://pan.baidu.com/s/1skBxqAp 密码: aebv
文件解压后复制到

/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport

文件夹下,然后重启Xcode,运行代码即可。

-原文链接-