Swift中如何在自定义弹窗扩展的UIAlertAction中获取UITextField输入值
Swift封装带输入框的UIAlertController获取输入值的解决方案
你无法拿到输入值的核心原因是:封装的
showAlertWithTextField方法中,UIAlertController属于方法内部的局部变量,外部调用时传入的UIAlertAction回调无法直接访问到这个内部实例,因此无法读取它的textFields属性。
方案一:优化封装结构(推荐)
把Alert的按钮逻辑也收拢到扩展内部,直接把输入值通过回调抛给调用方,封装更彻底,调用方不需要感知Alert的内部实现。
修改后的扩展代码:
import UIKit extension UIViewController { /// 弹出带单个输入框的Alert /// - Parameters: /// - title: 弹窗标题 /// - message: 弹窗提示内容 /// - confirmTitle: 确认按钮文案 /// - cancelTitle: 取消按钮文案 /// - confirmStyle: 确认按钮样式 /// - textFieldConfig: 输入框配置闭包,可自定义占位符、键盘类型等 /// - completion: 点击确认按钮的回调,返回输入框的内容 func showTextFieldAlert( title: String?, message: String?, confirmTitle: String = "确定", cancelTitle: String = "取消", confirmStyle: UIAlertAction.Style = .default, textFieldConfig: ((UITextField) -> Void)? = nil, completion: @escaping (String?) -> Void ) { let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) // 添加输入框,支持外部自定义配置 alert.addTextField { textField in textFieldConfig?(textField) } // 添加取消按钮 alert.addAction(UIAlertAction(title: cancelTitle, style: .cancel)) // 添加确认按钮,点击时返回输入值 alert.addAction(UIAlertAction(title: confirmTitle, style: confirmStyle, handler: { _ in let inputText = alert.textFields?.first?.text completion(inputText) })) present(alert, animated: true) } }
调用侧代码:
func showAlert() { showTextFieldAlert( title: "test", message: nil, confirmTitle: "Edit", confirmStyle: .destructive, textFieldConfig: { textField in // 可自由配置输入框属性 textField.placeholder = "请输入标题" textField.keyboardType = .default }, completion: { inputText in guard let title = inputText, !title.isEmpty else { return } print("title: \(title)") } ) }
方案二:兼容现有扩展结构
如果不想改动现有扩展的入参设计,可以通过外部提前持有输入框引用的方式实现:
调整扩展加配置参数:
func showAlertWithTextField( title: String?, message: String?, actions: [UIAlertAction], style: UIAlertController.Style, // 新增输入框配置参数 textFieldConfig: ((UITextField)->Void)?, completion: (() -> Void)? ) { let alert = UIAlertController(title: title, message: message, preferredStyle: style) alert.addTextField { textField in textFieldConfig?(textField) } actions.forEach { alert.addAction($0)} present(alert, animated: true, completion: completion) }
调用侧代码:
func showAlert() { // 提前声明弱引用变量持有输入框,避免循环引用 weak var inputTextField: UITextField? let editAction = UIAlertAction(title: "Edit", style: .destructive) { _ in if let title = inputTextField?.text { print("title: \(title)") } } // 调用时把输入框赋值给提前声明的变量 self.showAlertWithTextField( title: "test", message: nil, actions: [editAction], style: .alert, textFieldConfig: { textField in inputTextField = textField }, completion: nil ) }
内容的提问来源于stack exchange,提问作者Yuuu
相关产品推荐
相关产品推荐

