UIAlert中空文本框时弹窗抖动动画无法正常显示问题求助
解决UIAlert文本框为空时抖动动画不显示的问题
我太懂这个痛点了!现在的问题是点击「Add Item」按钮后,不管文本框空不空,弹窗都会直接关闭——你写的抖动动画根本没机会展示出来,这是因为UIAlertAction的默认行为就是触发后自动关闭弹窗,动画还没开始播放,弹窗已经消失了。
核心问题分析
你原来的逻辑是对的,但忽略了系统的默认规则:点击UIAlertAction后,系统会先执行你写的handler闭包,然后立刻关闭弹窗。所以当文本框为空时,你刚把动画添加到文本框,弹窗就被关掉了,自然看不到效果。
解决方案:手动控制弹窗关闭时机
我们需要让弹窗在文本框为空时保持显示,同时让动画正常播放。最佳做法是利用UIAdaptivePresentationControllerDelegate协议来控制弹窗的关闭权限,具体步骤如下:
1. 让ViewController遵守协议
首先,确保你的视图控制器遵守UIAdaptivePresentationControllerDelegate:
class YourViewController: UIViewController, UIAdaptivePresentationControllerDelegate { // 你的现有代码(比如itemArray、tableView等) }
2. 重构Alert创建逻辑
重新编写弹窗的创建代码,设置弹窗的presentationController代理,并在按钮点击时判断文本框状态:
@IBAction func showAddItemAlert(_ sender: UIBarButtonItem) { let alert = UIAlertController(title: "Add New Item", message: nil, preferredStyle: .alert) // 设置代理,用于控制弹窗是否允许关闭 alert.presentationController?.delegate = self // 添加文本框 alert.addTextField { textField in textField.placeholder = "Enter item name" } // 添加「Add Item」按钮 let addAction = UIAlertAction(title: "Add Item", style: .default) { [weak self] _ in guard let textField = alert.textFields?.first else { return } if let text = textField.text, !text.isEmpty { // 文本不为空,执行添加逻辑 self?.itemArray.append(text) self?.tableView.reloadData() } else { // 文本为空,播放抖动动画 textField.shake() } } // 添加「Cancel」按钮 let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) alert.addAction(addAction) alert.addAction(cancelAction) present(alert, animated: true) }
3. 实现代理方法控制弹窗关闭
添加代理方法,根据文本框是否为空,决定是否允许弹窗关闭:
func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool { guard let alert = presentationController.presentedViewController as? UIAlertController, let textField = alert.textFields?.first else { return true // 默认允许关闭 } // 文本框为空时返回false,阻止弹窗关闭;否则允许关闭 return !textField.text?.isEmpty ?? false }
4. 优化:封装抖动动画(可选)
把抖动动画封装成UITextField的扩展,让代码更简洁易复用:
extension UITextField { func shake() { let shakeAnim = CABasicAnimation(keyPath: "position") shakeAnim.duration = 0.07 shakeAnim.repeatCount = 4 shakeAnim.autoreverses = true shakeAnim.fromValue = NSValue(cgPoint: CGPoint(x: center.x - 10, y: center.y)) shakeAnim.toValue = NSValue(cgPoint: CGPoint(x: center.x + 10, y: center.y)) layer.add(shakeAnim, forKey: "shakeAnimation") } }
最终效果
现在点击「Add Item」按钮时:
- 如果文本框为空:弹窗保持显示,文本框会播放抖动动画,提示用户输入内容
- 如果文本框不为空:执行添加条目、刷新表格的逻辑,弹窗正常关闭
内容的提问来源于stack exchange,提问作者iArmvn
相关产品推荐
相关产品推荐

