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

如何在UIAlertAction中用for循环校验游戏名称并控制代码执行

问题:游戏名称重复校验失效,创建代码始终执行

我想通过UIAlertAction让用户输入游戏名称,然后和SingletonClass.shared.gamesArray里的游戏名称做校验:

  • 如果名称已存在,弹出提示告知用户,并回到原来的输入提示框
  • 如果不存在,执行创建新游戏的代码

现在我用for循环做了校验,但不管重复提示框弹不弹,后面的创建游戏代码都会执行。试过组合for循环和if语句,但不确定是不是最优方案,求建议和帮助。

我的代码:

@IBAction func savedGamePressed(_ sender: UIButton) {
    var textField = UITextField()
    
    let alert = UIAlertController(title: "Please Name This Game", message: "", preferredStyle: .alert)
    
    let action = UIAlertAction(title: "Save Game", style: .default){ [self](action) in
        //what happens once the user clicks the saved game button
        newGameName = textField.text!
        
        for game in SingletonClass.shared.gamesArray where newGameName == game.gameName {
            let alert = UIAlertController(title: "Name Already Used", message: "", preferredStyle: .alert)
            
            let action = UIAlertAction(title: "OK", style: .default){_ in
                alert.dismiss(animated: false)
                
                self.used = false
            }
            alert.addAction(action)
            
            present(alert, animated: true, completion: nil)
            
        }
        // stop code here if for loop alert pops up
        if used != false{
            let newGame = Games(context: SingletonClass.shared.context)
            newGame.gameName = newGameName
            newGame.gameSaved = true
            newGame.gameRounds = SingletonClass.shared.numberRounds[0].nRounds

问题分析

  1. 代码执行顺序问题:for循环仅在找到重复项时弹出提示,但不会中断后续代码执行——不管有没有找到重复,都会继续执行下面的创建游戏代码。
  2. 异步闭包逻辑无效:你在提示框的OK按钮回调里设置self.used = false,但这个回调是异步执行的,等用户点击OK时,后面的创建代码早就跑完了,根本起不到阻止作用。
  3. 未实现回到原输入框:当前逻辑下,用户关闭重复提示后,不会回到之前的输入AlertController。

优化后的代码

@IBAction func savedGamePressed(_ sender: UIButton) {
    // 封装输入框逻辑,方便重复调用
    func showGameNameInputAlert() {
        let alert = UIAlertController(title: "请输入游戏名称", message: "", preferredStyle: .alert)
        
        // 添加输入框(原代码里的textField赋值方式有问题,应该用addTextField)
        alert.addTextField { textField in
            textField.placeholder = "输入游戏名称"
        }
        
        let saveAction = UIAlertAction(title: "保存游戏", style: .default) { [weak self] _ in
            guard let self = self, 
                  let newGameName = alert.textFields?.first?.text, 
                  !newGameName.trimmingCharacters(in: .whitespaces).isEmpty else {
                // 处理空输入/全空格输入的情况
                return
            }
            
            // 用contains高效判断名称是否存在,替代手动for循环
            let nameExists = SingletonClass.shared.gamesArray.contains { game in
                game.gameName == newGameName
            }
            
            if nameExists {
                // 弹出重复提示,关闭后重新显示输入框
                let duplicateAlert = UIAlertController(title: "名称已被使用", message: "请选择其他名称", preferredStyle: .alert)
                let okAction = UIAlertAction(title: "确定", style: .default) { _ in
                    self.showGameNameInputAlert()
                }
                duplicateAlert.addAction(okAction)
                self.present(duplicateAlert, animated: true)
            } else {
                // 名称不存在,执行创建逻辑
                let newGame = Games(context: SingletonClass.shared.context)
                newGame.gameName = newGameName
                newGame.gameSaved = true
                newGame.gameRounds = SingletonClass.shared.numberRounds[0].nRounds
                
                // Core Data对象创建后必须保存才会持久化
                do {
                    try SingletonClass.shared.context.save()
                    // 可以在这里添加保存成功后的逻辑,比如返回列表页
                } catch {
                    print("保存游戏失败:\(error.localizedDescription)")
                }
            }
        }
        
        let cancelAction = UIAlertAction(title: "取消", style: .cancel)
        alert.addAction(saveAction)
        alert.addAction(cancelAction)
        
        present(alert, animated: true)
    }
    
    // 首次调用输入框
    showGameNameInputAlert()
}

新手开发建议

  • 优先使用数组高阶函数:用contains、first(where:)替代手动for循环,代码更简洁,可读性和效率更高。
  • 避免异步闭包控制同步代码:UIAlertAction的回调是异步的,不要依赖回调里的变量去控制后续同步代码的执行,直接在回调里分支处理逻辑即可。
  • 封装重复逻辑:把弹出输入框这类重复使用的UI逻辑封装成函数,减少代码冗余,也方便后续修改维护。
  • 处理边界情况:一定要处理空输入、全空格输入的情况,避免因为空字符串导致的崩溃或数据异常。
  • Core Data注意点:创建托管对象后必须调用context.save(),否则数据不会持久化到本地。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 10:25:20