6

我正在为 iOS 开发一个键盘扩展。在 iOS 9 上,除了键盘左边缘的按键外,按键会立即做出反应。那些反应大约有 0.2 秒的延迟。原因是触摸只是通过延迟传递到UIView我的键盘的根视图。在 iOS 8 上没有这样的延迟。

我的猜测是,这种延迟是由一些应该识别打开“正在运行的应用程序屏幕”的手势的逻辑引起的。这很好,但键盘上的延迟是不可接受的。有什么办法可以毫不拖延地获得这些事件吗?也许只是delaysTouchesBegan设置false一些UIGestureRecognizer

4

3 回答 3

2

这适用于使用更高版本 iOS 的任何人(这适用于我的 iOS 9 和 10)。我的问题是由于滑动返回手势干扰了我的 touchesBegan 方法,阻止它在屏幕的最左边缘触发,直到触摸结束,或者系统识别到该移动不是滑动到的移动回去的手势。

在控制器的 viewDidLoad 函数中,简单地说:

self.navigationController?.interactivePopGestureRecognizer?.delaysTouchesBegan = false
于 2017-08-27T07:25:30.643 回答
2

如果您有权访问viewwindow属性,则可以访问这些系统手势识别器并设置delaysTouchesBeganfalse

这是 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 和屏幕底部附近的延迟点击

于 2017-04-05T09:38:12.423 回答
1

自 iOS11 以来的官方解决方案是覆盖preferredScreenEdgesDeferringSystemGestures您的UIInputViewController.

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毫无延迟地获得状态更新。因此,您可以添加一个自定义手势识别器来处理触摸事件,而不是遵循下面相当混乱的解决方案。

您可以快速测试此添加UILongPressGestureRecognizerminimumPressDuration = 0您的控制视图。

另一种解决方案:

我最初的解决方法是调用touch downeffects inside hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView?,即使在视图的触摸延迟时也会调用它。

您必须忽略“真正的”触地事件,当它在大约 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:).

于 2020-05-02T03:56:27.060 回答