引言:为什么你的 UIAlertView 不工作(以及 Stack Overflow 有什么关系)
\n\n如果你曾经搜索过“How would I create a UIAlertView in Swift?”——你并不孤单。这个 Stack Overflow 上的问题已经积累了数十万次浏览。看起来似乎很简单?向用户显示一个带有“确定”按钮的弹出窗口。但在实践中,新手(不仅仅是新手)经常会掉进同样的陷阱。
\n\n在本文中,我们将分析在 Swift 中创建 UIAlertView 的 5 大错误,展示如何修复它们,并提供UIAlertController的现成代码——这是对已弃用 API 的现代替代方案。如果你想编写干净、无崩溃的工作代码,请继续阅读。
\n\n错误 #1:使用 UIAlertView 而不是 UIAlertController
\n\n最常见的错误是在现代 Swift 中尝试调用 UIAlertView。这个类早在 iOS 8 中就被标记为已弃用(deprecated)。如果你编写:
let alert = UIAlertView(title: "错误", message: "出了点问题", delegate: nil, cancelButtonTitle: "确定")\nalert.show()\n\n……那么编译器很可能会发出警告或错误。即使项目编译成功,在 iOS 13+ 上弹窗也无法正常工作。
\n\n为什么会这样?
\n苹果早在 iOS 8 中就用 UIAlertController 替换了 UIAlertView。旧类不再受支持,使用它可能导致意外行为。
如何修复?
\n使用 UIAlertController,并指定首选样式为 .alert 或 .actionSheet。以下是正确的代码:
let alert = UIAlertController(title: "错误",\n message: "出了点问题",\n preferredStyle: .alert)\nalert.addAction(UIAlertAction(title: "确定", style: .default))\npresent(alert, animated: true)\n\n请记住:在现代 Swift 中,UIAlertView 是遗留代码。始终使用 UIAlertController。
错误 #2:忘记调用 present()
\n\n即使你创建了 UIAlertController,但忘记显示它——什么也不会发生。字面意义上的。代码会执行,弹窗会在内存中创建,但用户看不到它。
典型错误示例:
\n\nfunc showAlert() {\n let alert = UIAlertController(title: "你好", message: "世界", preferredStyle: .alert)\n alert.addAction(UIAlertAction(title: "确定", style: .default))\n // 忘记调用 present!\n}\n\n结果:一片寂静。没有错误,没有弹窗。你会纳闷为什么代码不工作。
\n\n如何修复?
\n始终在当前视图控制器上调用 present(_:animated:completion:):
func showAlert() {\n let alert = UIAlertController(title: "你好", message: "世界", preferredStyle: .alert)\n alert.addAction(UIAlertAction(title: "确定", style: .default))\n present(alert, animated: true, completion: nil)\n}\n\n提示:如果你在闭包或异步代码中调用弹窗,请确保 self(视图控制器)仍然存在。否则会导致崩溃。
错误 #3:按钮点击处理不正确
\n\n在旧的 UIAlertView 中,我们使用委托方法 alertView(_:clickedButtonAt:)。在 UIAlertController 中则完全不同——使用闭包(closures)。
新手常常试图让类遵循 UIAlertViewDelegate 并实现委托方法,但这在 UIAlertController 中行不通。
错误做法:
\n\nclass ViewController: UIViewController, UIAlertViewDelegate {\n func showAlert() {\n let alert = UIAlertController(title: "问题", message: "你同意吗?", preferredStyle: .alert)\n alert.addAction(UIAlertAction(titl