You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何长按手势触发present时,ViewController被重复模态呈现两次?

解决长按手势触发两次ViewController模态呈现的问题

你遇到的重复弹窗问题,根源其实很简单——UILongPressGestureRecognizer和点击手势的触发逻辑不一样:点击手势只会在松开时触发一次回调,但长按手势会在手势开始、持续、结束等多个状态节点都调用你的处理方法,而你现在的代码没有判断手势状态,所以每次状态变化都会执行一次present,自然就弹出了两次甚至更多次。

具体修改方案

只需要在你的长按手势处理函数里,加一个手势状态的判断,只在手势刚刚开始的时候执行present操作就行:

  1. 首先修改手势处理函数,接收手势参数并判断状态:
@objc func easterEggScreenPresent(_ gesture: UILongPressGestureRecognizer){
    // 只在手势开始的瞬间执行present
    guard gesture.state == .began else { return }
    
    let eggVC = EasterEggViewController()
    ((UIApplication.shared.keyWindow?.rootViewController as? MainTabBarViewController)?.selectedViewController as? NavigationPodesavanjaViewController)?.visibleViewController?.present(eggVC, animated: true, completion: nil)
}
  1. 然后修改手势绑定的selector,要带上冒号(因为方法现在有参数了):
let longPressEgg = UILongPressGestureRecognizer()
// 注意selector后面的冒号,对应带参数的方法
longPressEgg.addTarget(self, action: #selector(easterEggScreenPresent(_:)))
easterEgg.addGestureRecognizer(longPressEgg)

额外优化建议

你通过keyWindow层层获取控制器的方式虽然解决了层级警告,但其实可以更简洁。如果这个长按手势是直接添加在那个TableViewController(也就是NavigationPodesavanjaViewController的visibleViewController)里的,那完全可以直接用self.present(...),省去多层强制解包的麻烦:

@objc func easterEggScreenPresent(_ gesture: UILongPressGestureRecognizer){
    guard gesture.state == .began else { return }
    
    let eggVC = EasterEggViewController()
    self.present(eggVC, animated: true, completion: nil)
}

这样既解决了重复弹窗的问题,代码也更清晰~

内容的提问来源于stack exchange,提问作者andrija

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:02:19