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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 13:00:00