在同一个 UIView 中多次点击手势检测
Posted
技术标签:
【中文标题】在同一个 UIView 中多次点击手势检测【英文标题】:Tap Gesture Detected Multiple Times in the same UIView 【发布时间】:2021-08-28 19:10:13 【问题描述】:目前,我正在尝试将 UITapGestureRecognizer
添加到 UIView
以启动计时器。但是,每当我错误地多次点击UIView
时,都会识别出多个手势,并且计时器会运行两次,或者比平时快几倍。
我想确保UIView
仅识别 1 个计时器动作/1 个轻按手势,并且第二次轻按将是多余的(稍后我将努力确保第 2 次轻按“停止”计时器)。
我尝试阅读this answer,但它并没有完全指导我如何防止第二次点击或根据状态自定义操作,我仍在努力解决这个问题,但我陷入了困境问题。
如果您对我如何解决此问题有任何见解,请提供帮助。
class ActiveExerciseTableViewCell: UITableViewCell, UITextFieldDelegate
var restTimer = Timer()
var restTimeRemaining: Int = 180
func setUpActiveExerciseUIViewLayout()
timerLabel.translatesAutoresizingMaskIntoConstraints = false
timerLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
timerLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: (contentView.frame.height-tableviewContentViewTabBarHeight)*0.55).isActive = true
timerLabel.widthAnchor.constraint(equalToConstant: contentView.frame.width * 0.7).isActive = true
timerLabel.heightAnchor.constraint(equalToConstant: 80).isActive = true
timerLabel.font = .boldSystemFont(ofSize: 64)
activeExerciseTimerUIView.translatesAutoresizingMaskIntoConstraints = false
activeExerciseTimerUIView.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
activeExerciseTimerUIView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: (contentView.frame.height-tableviewContentViewTabBarHeight)*0.25).isActive = true
activeExerciseTimerUIView.widthAnchor.constraint(equalToConstant: 225).isActive = true
activeExerciseTimerUIView.heightAnchor.constraint(equalToConstant: 225).isActive = true
let timerStartGesture = UITapGestureRecognizer(target: self, action: #selector(playTapped))
timerStartGesture.numberOfTapsRequired = 1
activeExerciseTimerUIView.addGestureRecognizer(timerStartGesture)
activeExerciseTimerUIView.isUserInteractionEnabled = true
@objc func playTapped(_ sender: Any)
restTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(step), userInfo: nil, repeats: true)
@IBAction func pauseTapped(_ sender: Any)
restTimer.invalidate()
@IBAction func resetTapped(_ sender: Any)
restTimer.invalidate()
restTimeRemaining = 180
timerLabel.text = "\(restTimeRemaining)"
@objc func step()
if restTimeRemaining > 0
restTimeRemaining -= 1
else
restTimer.invalidate()
restTimeRemaining = 180
timerLabel.text = prodTimeString(time: TimeInterval(restTimeRemaining))
func prodTimeString(time: TimeInterval) -> String
let Minutes = Int(time) / 60 % 60
let Seconds = Int(time) % 60
return String(format: "%02d:%02d", Minutes, Seconds)
【问题讨论】:
有点不相关,但我建议不要在ActiveExerciseTableViewCell
中使用Timer
之类的东西。当你滚动时这些会被重用,所以你以后可能会遇到一些奇怪的错误。最好在你的父视图控制器中管理它。
这是一个非常有用的信息。现在,我没有任何错误或问题。但是我确实理解您的观点,因为当我尝试实现键盘设置时遇到了类似的问题。最后,我不得不使用我的父视图。问题是 - 我还在学习,我不太清楚如何将 IBactions & objc func 连接到“UITableViewCell”类中的 UIcontrols。也许,我稍后会发布另一个问题。
您好 Aheze,我遇到了您提到的确切问题并发布了这个问题 - ***.com/questions/68975261/… 如果可以的话,我将不胜感激。我尝试将代码写入父控制器,但不知道如何通过“playTapped”等objective c方法传递“UILabel参数”,发现这样做很复杂。
【参考方案1】:
使用布尔值来处理状态变化:
class ActiveExerciseTableViewCell: UITableViewCell, UITextFieldDelegate
var restTimer = Timer()
var restTimeRemaining: Int = 180
var timerInitiated: Bool = false /// here!
func setUpActiveExerciseUIViewLayout()
timerLabel.translatesAutoresizingMaskIntoConstraints = false
timerLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
timerLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: (contentView.frame.height-tableviewContentViewTabBarHeight)*0.55).isActive = true
timerLabel.widthAnchor.constraint(equalToConstant: contentView.frame.width * 0.7).isActive = true
timerLabel.heightAnchor.constraint(equalToConstant: 80).isActive = true
timerLabel.font = .boldSystemFont(ofSize: 64)
activeExerciseTimerUIView.translatesAutoresizingMaskIntoConstraints = false
activeExerciseTimerUIView.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
activeExerciseTimerUIView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: (contentView.frame.height-tableviewContentViewTabBarHeight)*0.25).isActive = true
activeExerciseTimerUIView.widthAnchor.constraint(equalToConstant: 225).isActive = true
activeExerciseTimerUIView.heightAnchor.constraint(equalToConstant: 225).isActive = true
let timerStartGesture = UITapGestureRecognizer(target: self, action: #selector(playTapped))
timerStartGesture.numberOfTapsRequired = 1
activeExerciseTimerUIView.addGestureRecognizer(timerStartGesture)
activeExerciseTimerUIView.isUserInteractionEnabled = true
@objc func playTapped(_ sender: Any)
if !timerInitiated /// check here
restTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(step), userInfo: nil, repeats: true)
self.timerInitiated = true
@IBAction func pauseTapped(_ sender: Any)
restTimer.invalidate()
@IBAction func resetTapped(_ sender: Any)
restTimer.invalidate()
restTimeRemaining = 180
timerLabel.text = "\(restTimeRemaining)"
@objc func step()
if restTimeRemaining > 0
restTimeRemaining -= 1
else
restTimer.invalidate()
restTimeRemaining = 180
timerLabel.text = prodTimeString(time: TimeInterval(restTimeRemaining))
func prodTimeString(time: TimeInterval) -> String
let Minutes = Int(time) / 60 % 60
let Seconds = Int(time) % 60
return String(format: "%02d:%02d", Minutes, Seconds)
如果timerInitiated
布尔值为真,则表示练习已经开始,除非布尔值改变,否则不会再安排任何计时器。
【讨论】:
感谢您的回答:) 简单而优雅的解决方案以上是关于在同一个 UIView 中多次点击手势检测的主要内容,如果未能解决你的问题,请参考以下文章