UITouchEvent
阶段Began
,该touchesBegan:withEvent:
调用controllerA
中的controllerA
方法,该方法执行从controllerB
到UITouchEvent
的segue。< / LI>
Ended
阶段controllerA
,它会调用一些回调方法。问题:此回调方法的内容和位置是什么?它不在controllerB
中,而且不在{{1}}中。据我所知,这不是任何观点。但它存在。
答案 0 :(得分:3)
澄清一下,这是发生了什么(根据@switz的说法):
-touchesBegan:withEvent:
时,会显示一个视图控制器
模态地通过segue 问题是如何对被抬起的手指做出反应,因为 1}}未被调用。
简短的回答是呈现的视图控制器需要使用“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:
设置为UILongPressGestureRecognizer
,minimumPressDuration
设置为某个
可笑的高价值(因为你不希望运动取消触摸)。我
推荐这个因为0
是连续的
识别器,意味着它将为Began,Moved和Ended发送事件
建议的设置,它将发送它们以响应触摸开始,
移动,结束。更重要的是,一旦你的识别器开始处理触摸,
这会自动阻止任何其他识别器(例如滚动视图的平移
识别者)从“接管”和取消触摸。
请注意,如果您将手势识别器附加到scrollView本身
(例如allowableMovement
),但只想响应某些地点的触摸
(例如在一行上),那么你需要限制识别器。你可以使用
委托方法UILongPressGestureRecognizer
来做这件事
像这样:
UITableView
这样识别器不会阻止gestureRecognizer(_:shouldReceiveTouch:)
的{{1}}
当用户触摸桌子上的其他地方时滚动。