如何取消 LongPressGestureRecognizer?
How to cancel LongPressGestureRecognizer?
我有一个分配了 LongPressGestureRecognizer
的视图,它调用以下方法:
@IBAction func longPressOnView1Recognized(_ sender: UIGestureRecognizer) {
if sender.state == .began {
// this runs when user's finger is down a "long time"
}
if sender.state == .ended {
// this runs when user's finger goes up again after the .began state
}
}
这一切都按预期工作,但我正在尝试找到一种 (good/proper) 方式,能够以编程方式 cancel
长按识别器(在某些情况下),同时用户的手指还在下
也就是说,while用户的手指还在view上,识别器进入了.began状态,(但是before 用户已经抬起手指——在识别器进入 .ended 状态之前)...是否有一些代码我们可以 运行 来防止上述方法在用户抬起手指时触发...比如过早地告诉 IOS 在这个手势的剩余部分不再监听 UP 事件?
我读过这些 docs,但我对 IOS 触摸没有那么多经验,而且我似乎找不到任何为此目的而设计的方法。
我的 GestureRecognizer.reset()
似乎与我描述的不符。
我想到了两种可能:
1) 一个布尔标志,将进入 if sender.state == .ended {}
闭包
2) 这个:
myLongPressRecognizer.isEnabled = false
myLongPressRecognizer.isEnabled = true
这两个都有效,但似乎不太好。
您已经有了解决方案。切换 UILongPressGestureRecognizer
isEnabled
是最好的方法。设置 state
属性 是不可能的,因为它是一个 get-only 属性.
open var state: UIGestureRecognizer.State { get } // the current state of the gesture recognizer
isEnabled
属性 记录为:
default is YES. disabled gesture recognizers will not receive touches. when changed to NO the gesture recognizer will be cancelled if it's currently recognizing a gesture.
你们都很擅长禁用和重新启用手势识别器
myLongPressRecognizer.isEnabled = false
myLongPressRecognizer.isEnabled = true
完全正确。
我担心的是你不完全理解手势识别器。在处理手势识别器时,您应该始终使用 switch 语句。查看评论:
func handleLongPressGestureRecognizer(_ sender: UIGestureRecognizer) {
switch sender.state {
case .began:
// This will be called only once when the gesture starts
print("Long press did begin at \(sender.location(in: sender.view))")
case .changed:
// This will be called whenever your finger moves (at some frequency obviously).
// At this point your long press gesture is acting exactly the same as pan gesture
print("Long press changed position to \(sender.location(in: sender.view))")
case .ended:
// This is when user lifts his finger assuming the gesture was not canceled
print("Long press ended at \(sender.location(in: sender.view))")
case .cancelled:
// This is equally important as .ended case. You gesture may be canceled for many reasons like a system gesture overriding it. Make sure to implement logic here as well.
print("Long press canceled at \(sender.location(in: sender.view))")
case .failed, .possible:
// These 2 have been added additionally at some point. Useless as far I am concerned.
break
}
}
所以至少你应该处理取消状态。但还要注意,只要移动手势,就会触发更改的状态。
您可以导入手势识别器header:
import UIKit.UIGestureRecognizer
这将使 state
属性 成为读写 属性。因此,要取消手势,只需将其 state
更改为 .cancelled
.
因此,例如,您可以在识别长按手势识别器一秒后取消它,例如:
weak var timer: Timer?
@objc func handleLongPress(_ gesture: UILongPressGestureRecognizer) {
switch gesture.state {
case .began:
print("began")
timer?.invalidate()
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { _ in
gesture.state = .cancelled
}
case .ended, .cancelled:
print(gesture.state == .ended ? "Ended" : "Cancelled")
timer?.invalidate()
default:
break
}
}
我有一个分配了 LongPressGestureRecognizer
的视图,它调用以下方法:
@IBAction func longPressOnView1Recognized(_ sender: UIGestureRecognizer) {
if sender.state == .began {
// this runs when user's finger is down a "long time"
}
if sender.state == .ended {
// this runs when user's finger goes up again after the .began state
}
}
这一切都按预期工作,但我正在尝试找到一种 (good/proper) 方式,能够以编程方式 cancel
长按识别器(在某些情况下),同时用户的手指还在下
也就是说,while用户的手指还在view上,识别器进入了.began状态,(但是before 用户已经抬起手指——在识别器进入 .ended 状态之前)...是否有一些代码我们可以 运行 来防止上述方法在用户抬起手指时触发...比如过早地告诉 IOS 在这个手势的剩余部分不再监听 UP 事件?
我读过这些 docs,但我对 IOS 触摸没有那么多经验,而且我似乎找不到任何为此目的而设计的方法。
我的 GestureRecognizer.reset()
似乎与我描述的不符。
我想到了两种可能:
1) 一个布尔标志,将进入 if sender.state == .ended {}
闭包
2) 这个:
myLongPressRecognizer.isEnabled = false
myLongPressRecognizer.isEnabled = true
这两个都有效,但似乎不太好。
您已经有了解决方案。切换 UILongPressGestureRecognizer
isEnabled
是最好的方法。设置 state
属性 是不可能的,因为它是一个 get-only 属性.
open var state: UIGestureRecognizer.State { get } // the current state of the gesture recognizer
isEnabled
属性 记录为:
default is YES. disabled gesture recognizers will not receive touches. when changed to NO the gesture recognizer will be cancelled if it's currently recognizing a gesture.
你们都很擅长禁用和重新启用手势识别器
myLongPressRecognizer.isEnabled = false
myLongPressRecognizer.isEnabled = true
完全正确。
我担心的是你不完全理解手势识别器。在处理手势识别器时,您应该始终使用 switch 语句。查看评论:
func handleLongPressGestureRecognizer(_ sender: UIGestureRecognizer) {
switch sender.state {
case .began:
// This will be called only once when the gesture starts
print("Long press did begin at \(sender.location(in: sender.view))")
case .changed:
// This will be called whenever your finger moves (at some frequency obviously).
// At this point your long press gesture is acting exactly the same as pan gesture
print("Long press changed position to \(sender.location(in: sender.view))")
case .ended:
// This is when user lifts his finger assuming the gesture was not canceled
print("Long press ended at \(sender.location(in: sender.view))")
case .cancelled:
// This is equally important as .ended case. You gesture may be canceled for many reasons like a system gesture overriding it. Make sure to implement logic here as well.
print("Long press canceled at \(sender.location(in: sender.view))")
case .failed, .possible:
// These 2 have been added additionally at some point. Useless as far I am concerned.
break
}
}
所以至少你应该处理取消状态。但还要注意,只要移动手势,就会触发更改的状态。
您可以导入手势识别器header:
import UIKit.UIGestureRecognizer
这将使 state
属性 成为读写 属性。因此,要取消手势,只需将其 state
更改为 .cancelled
.
因此,例如,您可以在识别长按手势识别器一秒后取消它,例如:
weak var timer: Timer?
@objc func handleLongPress(_ gesture: UILongPressGestureRecognizer) {
switch gesture.state {
case .began:
print("began")
timer?.invalidate()
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { _ in
gesture.state = .cancelled
}
case .ended, .cancelled:
print(gesture.state == .ended ? "Ended" : "Cancelled")
timer?.invalidate()
default:
break
}
}