触摸事件仅在 iOS 9 的左屏幕边缘附近延迟。如何解决?
Posted
技术标签:
【中文标题】触摸事件仅在 iOS 9 的左屏幕边缘附近延迟。如何解决?【英文标题】:Touch events are delayed near left screen edge on iOS 9 only. How to fix it? 【发布时间】:2015-11-09 22:34:02 【问题描述】:我正在为 ios 开发键盘扩展。在 iOS 9 上,除了键盘左边缘的按键外,按键会立即做出反应。那些反应大约有 0.2 秒的延迟。原因是触摸只是通过延迟传递给UIView
,这是我键盘的根视图。在 iOS 8 上没有这样的延迟。
我的猜测是,这种延迟是由一些应该识别打开“正在运行的应用程序屏幕”手势的逻辑引起的。这很好,但键盘上的延迟是不可接受的。有什么办法可以毫不拖延地获得这些事件吗?也许只是在某些UIGestureRecognizer
上将delaysTouchesBegan
设置为false
?
【问题讨论】:
您找到解决方案了吗?我们遇到了同样的问题。令人沮丧! 我也想为此找到解决方案。 还是没有解决办法? @Rasto 我相信我已经提出了正确的解决方案。关心标记为已解决?) 【参考方案1】:如果您有权访问view
的window
属性,则可以访问这些系统手势识别器并将delaysTouchesBegan
设置为false
。
这是一个 swift 中的示例代码
if let window = view.window,
let recognizers = window.gestureRecognizers
recognizers.forEach r in
// add condition here to only affect recognizers that you need to
r.delaysTouchesBegan = false
也相关:UISystemGateGestureRecognizer and delayed taps near bottom of screen
【讨论】:
【参考方案2】:这适用于使用更高版本 iOS 的任何人(这适用于我的 iOS 9 和 10)。我的问题是由于滑动返回手势干扰了我的 touchesBegan 方法,阻止它在屏幕的最左边缘触发,直到触摸结束,或者系统识别出该移动不是滑动到返回手势。
在控制器的 viewDidLoad 函数中,简单地说:
self.navigationController?.interactivePopGestureRecognizer?.delaysTouchesBegan = false
【讨论】:
【参考方案3】:iOS11 以来的官方解决方案是覆盖您的UIInputViewController
的preferredScreenEdgesDeferringSystemGestures
。
https://developer.apple.com/documentation/uikit/uiviewcontroller/2887512-preferredscreenedgesdeferringsys
但是,它似乎至少不适用于 iOS 13。据我了解,这是因为preferredScreenEdgesDeferringSystemGestures
在UIInputViewController
中被覆盖时无法正常工作,至少在iOS 13 上是这样。
当您在常规视图控制器中覆盖此属性时,它会按预期工作:
override var preferredScreenEdgesDeferringSystemGestures: UIRectEdge
return [.left, .bottom, .right]
不过,UIInputViewController
并非如此。
UPD:看来,手势识别器仍会毫无延迟地获得.began
状态更新。因此,您可以添加自定义手势识别器来处理触摸事件,而不是遵循下面相当混乱的解决方案。
您可以将UILongPressGestureRecognizer
和minimumPressDuration = 0
快速添加到您的控制视图中进行测试。
另一种解决方案:
我最初的解决方法是在hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView?
中调用touch down
效果,即使视图的触摸延迟也会调用。
您必须忽略“真正的”触地事件,当它在大约 0.4 秒后触发或与 touch up inside
事件同时触发时。此外,最好仅在测试点位于约 20pt 横向边距内的情况下应用此 hack。
例如,对于一个等于屏幕宽度的视图,实现可能如下所示:
let edgeProtectedZoneWidth: CGFloat = 20
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView?
let result = super.hitTest(point, with: event)
guard result == self else
return result
if point.x < edgeProtectedZoneWidth || point.x > bounds.width-edgeProtectedZoneWidth
if !alreadyTriggeredFocus
isHighlighted = true
triggerFocus()
return result
private var alreadyTriggeredFocus: Bool = false
@objc override func triggerFocus()
guard !alreadyTriggeredFocus else return
super.triggerFocus()
alreadyTriggeredFocus = true
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?)
super.touchesCancelled(touches, with: event)
alreadyTriggeredFocus = false
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?)
super.touchesEnded(touches, with: event)
alreadyTriggeredFocus = false
...其中triggerFocus()
是您在touch down
事件上调用的方法。或者,您可以覆盖touchesBegan(_:with:)
。
【讨论】:
完善您的IOS 13
解决方案为我完成了这项工作(在 IOS 13 上)以上是关于触摸事件仅在 iOS 9 的左屏幕边缘附近延迟。如何解决?的主要内容,如果未能解决你的问题,请参考以下文章