ios手势识别代理

简介:

之前做优质派时写了一篇文章,由于当时做项目时这个主控制器就是RootViewController,虽然用的是ScrollView但也没考虑到导航栏的手势返回的问题 ,现在做小区宝3.0的闪购订单,用之前的就有问题了。导航栏的返回手势用不了,根据响应者链和响应事件,手势被ScrollView识别了,就到不了导航的手势识别,所以导致无法手势返回。

要解决这个问题首先要了解下手势识别代理:

iOS的手势识别模型其实是一个状态机

所有手势识别从一个可能状态(UIGestureRecognizerStatePossible)开始,然后开始分析、识别手势,如果识别失败将会进入失败状(UIGestureRecognizerStateFailed)。
如果识别成功,进入成功状态(UIGestureRecognizerStateRecognized)
对于连续性的手势,手势识别从Possible进入Began(UIGestureRecognizerStateBegan) ,然后会进入Change (UIGestureRecognizerStateChanged)状态,并在Change状态循环,在最后用户手指离开屏幕的时候会进入End(UIGestureRecognizerStateEnded)状态
连续手势也会从Change进入cancel (UIGestureRecognizerStateCancelled),如果判断手势已经不符合该要求了。
每次Gesture recognizer改变状态的时候都会发送一个action message到target,知道Failed或者Cancel。
有时候会出现iOS判断该手势符合多个条件,而用户此时只想要其中一种,这个情况下可以调用 requireGestureRecognizerToFail: ,该方法会让当前手势对象根据指定对象状态来进行下一步操作。如果指定对象进入Begin状态,当前对象直接进入Failed;如果指定对象进入Failed或Cancel状态,当前对象会进入Begin状态。这里就涉及到了不同手势之间执行的问题。(如果想要单击和双击都要执行,并分别执行不同的逻辑,这里可以先让单机等待双击失败在执行,但这样会导致单击事件稍微延迟执行,因为单击事件需要等待双击事件失败)。
可以选择不让接收、分析手势事件,通过 gestureRecognizer:shouldReceiveTouch: 在最开始的时候允许、拒绝接收手势时间;如果想延后判断则可以通过 gestureRecognizerShouldBegin:,如果返回No则会导致Failed时间
如果想要同时接收两个事件,就调用gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: 默认这个方法返回No,返回Yes则运行同时运行
单向影响,事件A和B, 如果想要让A影响B,但不想让B影响A,则可以通过重载方法 canPreventGestureRecognizer: 或者canBePreventedByGestureRecognizer:实现,比如
[rotationGestureRecognizer canPreventGestureRecognizer:pinchGestureRecognizer];
Touch事件传递过程是上到下,也就是从App->Window->View的过程
Touch事件,window会让Gesture recognizer优先分析touch对象,如果Gesture recognizer成功识别这些对象,touch事件就不会执行。总结就是Gesture recognizer的优先级会低于touch事件
影响touch传递给views
delaysTouchesBegan 阻止在Begin阶段Windows交付touch事件
delaysTouchesEnded Window不会在Enable阶段交付Touch事件
Gesture Recognizer是iOS定制的一些Touch事件类型,Dev可以订制自己的Gesture Recognizer,这里要继承UIGestureRecognizer并覆盖主要的四个类。


- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;

返回值是返回是否生效。此方法在gesture recognizer视图转出UIGestureRecognizerStatePossible状态时调用,如果返回NO,则转换到UIGestureRecognizerStateFailed;如果返回YES,则继续识别触摸序列.(默认情况下为YES)


- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;

这个方法返回值是用来表示手势是否共存的。只要返回YES,另外就不用管了,因为共存,所以共存,共同响应.也就是说两个gesture recognizers的delegate方法只要任意一个返回YES,则这两个就可以同时识别;只有两个都返回NO的时候,才是互斥的。默认情况下是返回NO。

一个控件的手势识别后是否阻断手势识别继续向下传播,默认返回NO;如果为YES,响应者链上层对象触发手势识别后,如果下层对象也添加了手势并成功识别也会继续执行,否则上层对象识别后则不再继续传播;


- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer NS_AVAILABLE_IOS(7_0);
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer NS_AVAILABLE_IOS(7_0);

这个两个成对的方法比较有趣,一个是前面失效后面生效,另外一个相反


- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;

在toucheBegan这个方法之前,也就是在手势状态为began之前?

此方法在window对象在有触摸事件发生时,调用gesture recognizer的touchesBegan:withEvent:方法之前调用,如果返回NO,则gesture recognizer不会看到此触摸事件。(默认情况下为YES).


相关文章
|
存储 API iOS开发
苹果手机iOS如何使用http代理
我们使用苹果手机访问网络时,有时候需要配置代理服务器。下面就来介绍一下。
苹果手机iOS如何使用http代理
|
iOS开发
iOS代理 通知 block传值的规范写法
iOS代理 通知 block传值的规范写法
146 0
|
C语言 iOS开发
IOS中block和代理
从ios4开始引入block,就是代码块,结构类c语言 基本结构 返回值 (^block名称)(参数):int(^BlockName)(int):返回值为int型,参数是一个int值的叫BlockName的block
|
缓存 编解码 API
淘票票 iOS 客户端:视频本地代理与缓存方案
提高客户端视频起播速度一直是比较关键的优化点。如何提高起播速度?除了通过优化网络、提高服务器带宽、优化视频文件码率帧率等常规方案外,还可以从哪些方面进行优化呢?一起来看看吧!
淘票票 iOS 客户端:视频本地代理与缓存方案
|
iOS开发 索引
iOS UITableView代理方法详解
iOS UITableView代理方法详解
182 0
|
iOS开发 开发者 编译器
iOS开发--通知,代理,KVO的区别,以及通知的多线程问题
1. delegate 当我们第一次编写ios应用时,我们注意到不断的在使用“delegate”,并且贯穿于整个SDK。delegation模式不是IOS特有的模式,而是依赖与你过去拥有的编程背景。针对它的优势以及为什么经常使用到,这种模式可能不是很明显的。