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

