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

iOS桌游追踪应用TextView代理触发Segue重复执行问题排查

解决TextView触发Segue执行两次的问题

你的问题根源在于textViewShouldBeginEditing代理方法可能被UIKit多次调用(比如系统内部状态更新、快速重复点击等场景),导致performSegue被执行多次。下面提供两种更优雅的解决方案,比时间判断的临时方法更可靠:

方法一:添加执行标记防止重复触发

通过一个布尔变量标记Segue是否正在执行,避免重复调用。

步骤1:添加实例变量

在你的AddMatchViewController中添加一个私有变量:

private var isSegueInProgress = false

步骤2:修改代理方法

更新textViewShouldBeginEditing,先检查标记再执行Segue:

func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
    // 如果Segue正在执行,直接返回false
    guard !isSegueInProgress else { return false }
    
    isSegueInProgress = true
    
    // 原来的SegueKey赋值逻辑
    if textView == playersNameView { segueKey = "all" }
    else if textView == winnersNameView { segueKey = "winners" }
    else if textView == loosersNameView { segueKey = "loosers" }
    
    // 执行Segue的逻辑
    if textView == pointsView {
        performSegue(withIdentifier: "addPoints", sender: self)
    } else if [playersNameView, winnersNameView, loosersNameView].contains(textView) {
        performSegue(withIdentifier: "choosePlayers", sender: self)
    }
    
    return false
}

步骤3:重置标记

当从子页面返回时,重置标记以允许再次触发Segue,在viewWillAppear中添加:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    isSegueInProgress = false
}

方法二:用Tap手势替代代理方法(推荐)

直接给TextView添加点击手势,完全避开代理方法的不确定性,逻辑更可控。

步骤1:添加Tap手势

在viewDidLoad中给每个需要触发Segue的TextView添加手势:

override func viewDidLoad() {
    super.viewDidLoad()
    
    // 为playersNameView添加点击手势
    let playersTap = UITapGestureRecognizer(target: self, action: #selector(handlePlayersTap))
    playersNameView.addGestureRecognizer(playersTap)
    playersNameView.isUserInteractionEnabled = true
    
    // 为winnersNameView添加点击手势
    let winnersTap = UITapGestureRecognizer(target: self, action: #selector(handleWinnersTap))
    winnersNameView.addGestureRecognizer(winnersTap)
    winnersNameView.isUserInteractionEnabled = true
    
    // 为loosersNameView添加点击手势
    let loosersTap = UITapGestureRecognizer(target: self, action: #selector(handleLoosersTap))
    loosersNameView.addGestureRecognizer(loosersTap)
    loosersNameView.isUserInteractionEnabled = true
    
    // 为pointsView添加点击手势
    let pointsTap = UITapGestureRecognizer(target: self, action: #selector(handlePointsTap))
    pointsView.addGestureRecognizer(pointsTap)
    pointsView.isUserInteractionEnabled = true
}

步骤2:实现手势响应方法

添加对应的Selector方法处理点击事件:

@objc private func handlePlayersTap() {
    segueKey = "all"
    performSegue(withIdentifier: "choosePlayers", sender: self)
}

@objc private func handleWinnersTap() {
    segueKey = "winners"
    performSegue(withIdentifier: "choosePlayers", sender: self)
}

@objc private func handleLoosersTap() {
    segueKey = "loosers"
    performSegue(withIdentifier: "choosePlayers", sender: self)
}

@objc private func handlePointsTap() {
    performSegue(withIdentifier: "addPoints", sender: self)
}

步骤3:移除代理方法

现在可以删除textViewShouldBeginEditing代理方法了,因为所有触发逻辑都由Tap手势接管。

两种方法对比

  • 方法一:改动小,适合快速修复现有代码,保留代理方法的逻辑结构。
  • 方法二:更彻底,完全避免了UIKit代理方法的潜在多次调用问题,代码逻辑更清晰,推荐作为长期解决方案。

内容的提问来源于stack exchange,提问作者Przemysław Szafulski

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:55:33