iOS:检测触摸,触发,修饰

时间:2014-03-16 06:51:40

标签: ios iphone objective-c

  1. 用户将手指放在屏幕上。这会触发UITouchEvent阶段Began,该touchesBegan:withEvent:调用controllerA中的controllerA方法,该方法执行从controllerBUITouchEvent的segue。< / LI>
  2. 用户将手指从屏幕上抬起。这会触发Ended阶段controllerA,它会调用一些回调方法。
  3. 问题:此回调方法的内容和位置是什么?它不在controllerB中,而且不在{{1}}中。据我所知,这不是任何观点。但它存在。

1 个答案:

答案 0 :(得分:3)

澄清一下,这是发生了什么(根据@switz的说法):

  • 在回复-touchesBegan:withEvent:时,会显示一个视图控制器 模态地通过segue
  • 当用户抬起手指时,应取消视图控制器。

问题是如何对被抬起的手指做出反应,因为

简短的回答是呈现的视图控制器需要使用“Over Full” 屏幕“-touchesEnded:withEvent:而不是默认的”全屏“样式 (这可以指定为segue的表示样式,或者如果 这是“默认”,然后是呈现的视图控制器的演示样式。)

长答案需要简要概述触控处理的工作原理。这个 解释忽略手势识别器:

当触摸开始时,它会传递到包含“触摸”的“最顶层”视图 接触点。从那里它被传递到响应链直到一些 对象决定处理触摸(通过实现表示 modalPresentationStyle而不是致电-touchesBegan:withEvent:)。

交付后续的触摸更改(例如移动,结束,取消) 接受触摸的同一观点。该观点将继续收到 触摸事件直到触摸完成或取消。

当应用程序移动到后台时触摸会被取消(因为 例如打来电话),或者像super这样的UIKit课程决定 它需要接管触摸处理(因为手指移动得足够远) 它看起来像用户想要滚动)。这里还有一些有趣的东西 使用UIScrollView,但可以忽略。

但是有一个皱纹,没有记录的东西:只接触交付 只要视图与窗口保持关联,就会发生这种情况。如果认为那个 被认为是“最顶层”(与UIScrollView.delaysContentTouches相关联的视图) 从窗口移开,然后触摸被认为已经消失, 重要的是,没有任何事件可以再发送给任何人。这是 即使有问题的视图不是处理触摸的对象,也是如此。

最后的皱纹是造成这个问题的原因。因为默认 “全屏”演示文稿样式实际上删除旧视图控制器 从窗口查看,触摸处理立即停止。但是,“结束了 全屏“演示风格不会删除它,它只是掩盖了旧的 查看与一个。 “全屏幕”通常在呈现视图时使用 控制器不完全不透明,但在这种情况下我们正在使用它,所以触摸 处理不会中断。


但这不是全部。这里还有另一个问题,那就是当时的观点 被感动的生活在UITouch内(可滚动或可滚动的) 总是反弹)。在这种情况下,即使使用“全屏幕”,您也会发现, 触摸事件继续传递,手指移动一下 突然导致触摸被取消。这是因为UIScrollView 不知道它已被掩盖,并已决定用户实际上正在尝试 滚动。这会导致它取消触摸。

但是有一个解决方案。这有点难看,但解决办法是 执行时立即取消任何封闭滚动视图上的任何滚动 塞古。这可以使用以下代码完成:

UIScrollView

当然,如果没有手势,触摸处理的讨论就不会完整 识别器。手势识别器几乎可以改变触摸的一切 处理。他们可以在任何触摸上获得第一个dib,并且可以中断视图触摸 随时处理。例如,class ViewController: UIViewController { // this is called from -touchesBegan:withEvent: from a child view // the child view is `sender` func touchDown(sender: UIView) { var view = sender.superview while view != nil { if let scrollView = view as? UIScrollView { // toggle the panGestureRecognizer enabled state to immediately // cause it to fail. let enabled = scrollView.panGestureRecognizer.enabled scrollView.panGestureRecognizer.enabled = true scrollView.panGestureRecognizer.enabled = enabled } view = view?.superview } performSegueWithIdentifier(identifier, sender: self) } // ... } 的{​​{1}} 是什么用于滚动,当它进入“开始”状态(因为 用户已经移动了足够的手指),这就是导致触摸的原因 取消。

所以考虑到这一点,这里真正最好的解决方案是不实施 完全UIScrollView,但要使用手势识别器。最简单的 这里的解决方案是使用UIPanGestureRecognizer -touchesBegan:withEvent:设置为UILongPressGestureRecognizerminimumPressDuration设置为某个 可笑的高价值(因为你不希望运动取消触摸)。我 推荐这个因为0是连续的 识别器,意味着它将为Began,Moved和Ended发送事件 建议的设置,它将发送它们以响应触摸开始, 移动,结束。更重要的是,一旦你的识别器开始处理触摸, 这会自动阻止任何其他识别器(例如滚动视图的平移 识别者)从“接管”和取消触摸。


请注意,如果您将手势识别器附加到scrollView本身 (例如allowableMovement),但只想响应某些地点的触摸 (例如在一行上),那么你需要限制识别器。你可以使用 委托方法UILongPressGestureRecognizer来做这件事 像这样:

UITableView

这样识别器不会阻止gestureRecognizer(_:shouldReceiveTouch:)的{​​{1}} 当用户触摸桌子上的其他地方时滚动。