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

Swift 5中如何获取程序动态添加的Button与TextField对应数据

动态表单控件数据绑定与存储解决方案

核心实现逻辑是给每个动态生成的控件绑定唯一业务标识,搭配全局配置容器和结果存储容器,即可实现控件与对应数据的一一绑定,无需为每个控件单独声明变量。

1. 定义数据模型与全局存储属性

首先定义表单控件的配置模型,以及全局的存储属性:

// 表单控件类型枚举
enum FormItemType {
    case button(options: [String]) // 按钮类型存储对应的ActionSheet选项
    case textField
}

// 表单控件配置模型
struct FormItem {
    let type: FormItemType
    let uniqueKey: String // 与JSON字段对应的唯一标识,用来关联存储结果
    let placeholder: String
}

// 全局存储属性
private var formItemList: [FormItem] = [] // 存储所有解析后的控件配置
private var formResultDict: [String: Any] = [:] // 存储所有控件的输入/选择结果,key为控件的uniqueKey

2. 改造控件生成方法,绑定唯一标识

修改原有控件生成方法,传入完整的控件配置,同时给控件绑定唯一标识:

按钮生成方法改造

func createButton(item: FormItem){
    let button = UIButton()
    button.setTitle(item.placeholder, for: .normal)
    button.setTitleColor(.blue, for: .normal)
    button.backgroundColor = .systemGray
    button.frame = CGRect(x: 0, y: 0, width: view.bounds.width, height: 40)
    // 绑定唯一标识到系统自带的accessibilityIdentifier属性,无需自定义关联对象
    button.accessibilityIdentifier = item.uniqueKey
    button.addTarget(self, action: #selector(buttonClicked(sender:)), for: .touchUpInside)
    formStackView.addArrangedSubview(button)
    formStackView.translatesAutoresizingMaskIntoConstraints = false
}

文本框生成方法改造

func createTextField(item: FormItem){
    let textField = SkyFloatingLabelTextField(frame: CGRect(x: 0, y: 0, width: view.bounds.width, height: 40))
    textField.placeholder = item.placeholder
    // 绑定唯一标识
    textField.accessibilityIdentifier = item.uniqueKey
    textField.font = .systemFont(ofSize: 15)
    textField.autocorrectionType = .no
    textField.clearButtonMode = .whileEditing
    textField.contentVerticalAlignment = .center
    textField.delegate = self
    textField.translatesAutoresizingMaskIntoConstraints = false
    textField.selectedTitleColor = Utility.GlobalVariable.yellowColor
    textField.selectedLineColor = Utility.GlobalVariable.yellowColor
    textField.tintColor = Utility.GlobalVariable.blueColor
    formStackView.spacing = 8
    formStackView.addArrangedSubview(textField)
}

3. 实现交互事件的存储逻辑

按钮点击事件处理

@objc private func buttonClicked(sender: UIButton) {
    // 获取当前按钮的唯一标识,找到对应的配置
    guard let key = sender.accessibilityIdentifier,
          let item = formItemList.first(where: { $0.uniqueKey == key }),
          case .button(let options) = item.type else { return }
    
    // 弹出ActionSheet
    let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
    options.forEach { option in
        alert.addAction(UIAlertAction(title: option, style: .default, handler: { [weak self] _ in
            guard let self = self else { return }
            // 将选中结果存入结果字典的对应key下
            self.formResultDict[key] = option
        }))
    }
    alert.addAction(UIAlertAction(title: "取消", style: .cancel))
    present(alert, animated: true)
}

文本框输入结果处理

实现UITextFieldDelegate代理方法,存储输入内容:

extension YourViewController: UITextFieldDelegate {
    func textFieldDidEndEditing(_ textField: UITextField) {
        guard let key = textField.accessibilityIdentifier else { return }
        // 将输入内容存入结果字典的对应key下
        formResultDict[key] = textField.text ?? ""
    }
    
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }
}

4. JSON解析生成表单示例

遍历JSON生成控件配置,同时渲染表单:

func renderForm(json: [[String: Any]]) {
    formItemList.removeAll()
    formStackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
    
    json.forEach { config in
        let type = config["type"] as? String ?? ""
        let uniqueKey = config["key"] as? String ?? ""
        let placeholder = config["placeholder"] as? String ?? ""
        
        if type == "button" {
            let options = config["options"] as? [String] ?? []
            let item = FormItem(type: .button(options: options), uniqueKey: uniqueKey, placeholder: placeholder)
            formItemList.append(item)
            createButton(item: item)
        } else if type == "textField" {
            let item = FormItem(type: .textField, uniqueKey: uniqueKey, placeholder: placeholder)
            formItemList.append(item)
            createTextField(item: item)
        }
    }
}

后续需要获取任意控件的结果时,直接通过对应唯一key从formResultDict中读取即可。


内容的提问来源于stack exchange,提问作者Bilal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 08:09:03