ios 关于UIView 的multipleTouchEnabled 和 exclusiveTouch
做项目时发现,在一个界面上的2个button竟然可以同时点击,依次push进去了2个 controller!我就产生了疑问,一个view的multipleTouchEnabled属性默认是false啊,那怎么会可以同时点击这个view上的2个子view呢?原来是对multipleTouchEnabled属性理解不对!下面看看对这个属性的理解。
multipleTouchEnabled的官方解释如下:
When set to true, the receiver receives all touches associated with a multi-touch sequence. When set to false, the receiver receives only the first touch event in a multi-touch sequence. The default value of this property is false. Other views in the same window can still receive touch events when this property is false. If you want this view to handle multi-touch events exclusively, set the values of both this property and the exclusiveTouch property to true.
exclusiveTouch的官方解释如下:
Setting this property to true causes the receiver to block the delivery of touch events to other views in the same window. The default value of this property is false.
注意:touch events的发送,是以window为一个组,而不是某个在window下的子view。 看到这里其实就可以得出结论了,如果你不想让2个button同时点击,只需要把它们的exclusiveTouch都设定为YES,就行了!multipleTouchEnabled没这个作用,我用错了属性!
参考的官方文档 Event Handling Guide,这个文档需要仔细阅读!
一个父view的multipleTouchEnabled属性不会影响它的子view的multipleTouchEnabled属性,也就是说,在一个multipleTouchEnabled = false的父view里,仍然可以有接受多个手指点击消息的子view。
再来看这个函数touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent),这里有2个参数,官方说明如下:
The set object. The passed-in NSSet contains all touches that are new or have changed in the phase represented by the method, such as UITouchPhaseBegan for the touchesBegan:withEvent: method.
The event object. The passed-in UIEvent object contains all of the touches for a given multitouch sequence.
The multipleTouchEnabled property is set to NO by default, which means that a view receives only the first touch in a multitouch sequence. When this property is disabled, you can retrieve a touch object by calling the anyObject method on the set object because there is only one object in the set.
下面是另一部分解释
The set of touches is a set (NSSet) of UITouch objects, representing new or changed touches for that phase. For example, when a touch transitions from the Began phase to the Moved phase, the app calls the touchesMoved:withEvent: method. The set of touches passed in to the touchesMoved:withEvent: method will now include this touch and all other touches in the Moved phase. The other parameter is an event (UIEvent object) that includes all touch objects for the event. This differs from the set of touches because some of the touch objects in the event may not have changed since the previous event message.
这里提到了一个名词 a multitouch sequence,一个sequence指从第一个手指按下到最后一个手指抬起,也可以通过以下的话理解:
iOS recognizes touches as part of a multitouch sequence. During a multitouch sequence, the app sends a series of event messages to the target responder.
上面的意思就是ios把所有的touch事件都作为 a multitouch sequence 的一部分,在a multitouch sequence生命周期内,不断发送touch event到target。
Each of these touch methods correspond to a touch phase: Began, Moved, Ended, and Canceled. When there are new or changed touches for a given phase, the app object calls one of these methods. Each method takes two parameters: a set of touches and an event.
所谓的multipleTouchEnabled = false 指的是这个view 只接收一个multitouch sequence中的第一个点在自己上面的手指的event信息,其余的手指event变化信息,都不会被这个view理会,所以对于一个multipleTouchEnabled = false的view来说,touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) ,第一个参数中永远只有一个touch对象,就是那个手指的event信息,而后边的event则会包含整个multitouch sequence 中的点击信息。
因此,可以看出multipleTouchEnabled这个属性不是为了控制这个view下的整个 tree 的点击控制的。这就导致了即使在一个multipleTouchEnabled=false的view上,放置了多个button,可以用多个手指同时点击这些button!
我们看一个例子,代码如下
class TouchView: UIView {
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
var touchSet = event.allTouches()
println("touchesBegan...touches set count is \(touches.count)")
println("UIEvent touch count is \(touchSet!.count)")
}
}
class ViewController: UIViewController {
@IBOutlet weak var view1: UIView!
@IBOutlet weak var view2: UIView!
override func viewDidLoad() {
super.viewDidLoad()
self.view.multipleTouchEnabled = false
view1.multipleTouchEnabled = true
view2.multipleTouchEnabled = false
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
println("self view touchesBegan.....")
}
}
界面截图如下

黄色是self.view 蓝色和红色是2个touchview,我们的点击方式如下
1.点击蓝色view,不放开
2.点击蓝色view,不放开
3.点击红色view,不放开
4.点击红色view,不放开
5.点击蓝色view,不放开
控制台输出如下:
touchesBegan...touches set count is
UIEvent touch count is
touchesBegan...touches set count is
UIEvent touch count is
touchesBegan...touches set count is 1
UIEvent touch count is 3
touchesBegan...touches set count is
UIEvent touch count is
这里的第三条是红色view第一次点击的输出,第二次的红色view点击输出没有,因为它的view2.multipleTouchEnabled = false
再来另一个测试:
1.点击黄色,不放开
2.点击蓝色,不放
3.点击红色,不放
输出如下:
self view touchesBegan.....
touchesBegan...touches set count is
UIEvent touch count is
touchesBegan...touches set count is
UIEvent touch count is
另外说一点,如果这里我们没有对红色和蓝色的类重写 touchesBegan 方法,那么系统默认会把消息交给 self.view 也就是黄色view处理。
ios 关于UIView 的multipleTouchEnabled 和 exclusiveTouch的更多相关文章
- 荼菜的iOS笔记--UIView的几个Block动画
前言:我的第一篇文章荼菜的iOS笔记–Core Animation 核心动画算是比较详细讲了核心动画的用法,但是如你上篇看到的,有时我们只是想实现一些很小的动画,这时再用coreAnimation就会 ...
- iOS学习——UIView的研究
在iOS开发中,我们知道有一个共同的基类——NSObject,但是对于界面视图而言,UIView是非常重要的一个类,UIView是很多视图控件的基类,因此,对于UIView的学习闲的非常有必要.在iO ...
- iOS开发UIView.h简介
1.UICoordinateSpace不同坐标空间的坐标切换 @protocol UICoordinateSpace <NSObject> //将当前的坐标空间点转换到指定的坐标空间 - ...
- iOS 使用UIView的一种有效方法
在一个典型的MVC结构 中,Model部分负责保存目标数据,View部分主要负责实现数据的界面以及将数据显示出来,二者在Controller的操作下协同工作.在iOS应用中,View的实现主要由UIV ...
- IOS自定义UIView
IOS中一般会用到几种方式自定义UIView 1.继承之UIView的存代码的自定义View 2.使用xib和代码一起使用的自定义View 3.存xib的自定义View(不需要业务处理的那种) 本文主 ...
- OpenGL ES: iOS 自定义 UIView 响应屏幕旋转
iOS下使用OpenGL 如果使用GLKit View 那么不用担心屏幕旋转的问题,说明如下: If you change the size, scale factor, or drawable pr ...
- iOS:UIView的CALayer基本演练
UIView的CALayer基本演练的属性和注意事项: 在UIView中创建一个按钮UIButton,然后设置UIButton的Layer属性 –圆角.边框.阴影及3D形变属性 注意: 1.在UIVi ...
- IOS设置UIView的边框为圆角
iOS 系统自带的 View 组件都是正方形的,看起来都太生硬,有时候我需要变成圆角形式,如下图: 具体的实现是使用QuartzCore库,下面我具体的描述一下实现过程: • 首先 ...
- iOS 中 UIView 和 CALayer 的关系
UIView 有一个名叫 layer ,类型为 CALayer 的对象属性,它们的行为很相似,主要区别在于:CALayer 继承自 NSObject ,不能够响应事件. 这是因为 UIView 除了负 ...
随机推荐
- Win8/Win10无法打开这个应用 内置管理员账户
现在装win10系统的同伴越来越多了,相比于win7,win10在某些设置方面也有些变化,比如我们在使用win8或者win10时,会碰到如图所示的对话框: Windows10/Windows8无法使用 ...
- fedora23忘记root密码怎么办??
fedora23使用的是uefi, 不是 传统的grub 所以在编辑grub的时候, 跟以前的版本略有不同 最最重要的是: 在编辑启动条目的时候, 那个 linuxefi ... vmlinuz... ...
- Emacs教程
中文 http://www.cnblogs.com/robertzml/category/209299.html 英文 http://ergoemacs.org/emacs/emacs_fun.htm ...
- [译]git status
git status git status命令能展示工作目录和stage区的状态. 使用他你能看到那些修改被staged到了, 哪些没有, 哪些文件没有被Git tracked到. git statu ...
- PHP的 Mysqli扩展库的多语句执行
$mysqli->multi_query($sqls); 执行多个sql语句,返回true/false 有结果集时,使用 $mysqli->store_result(); 来获取结 ...
- MapServer+TileCache+Apache+Python24 构建KS数据服务器
刚刚配置好TileCache,准备开工. 期间碰到多种配置的问题,罗列一下. 1.mod_python的一个最主要优点就是在性能上超越传统CGI.所以使用mod_python替代CGI.前提是安装好a ...
- Redis优化之CPU充分利用
Linux Redis Server之CPU充分利用 不知道大家有没有注意到你们公司的集群配置是否是有一种配置是这样的: 多个Redis Server分布在同一个节点,只是端口不同,如果有的话,应该是 ...
- PHPCMS几个有用的全局函数
1.$site_setting = get_site_setting($siteid); 这个get_site_setting()函数读取的是多站点中$siteid站点的相关配置,具体位置在网站根 ...
- leetcode 278. First Bad Version
You are a product manager and currently leading a team to develop a new product. Unfortunately, the ...
- Android学习笔记(三)——初探Intent
//此系列博文是<第一行Android代码>的学习笔记,如有错漏,欢迎指正! Intent 是 Android 程序中各组件之间进行交互的一种重要方式,它不仅可以指明当前组件想要执行的动作 ...