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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:03:00