Swift中创建多Picker View:TextField唤起对应Picker的问题求助
解决Swift中两个TextField唤起对应Picker View的问题
嘿,我明白你的问题了——你想让两个 TextField 分别唤起对应数据源的 Picker View,但现在不管点哪个都只弹出同一个,而且自定义的处理函数没起作用。别着急,我给你一个清晰的修改方案,核心是通过区分点击的 TextField 来切换 Picker 的数据源:
核心思路
我们不需要创建两个独立的 Picker View(当然也可以,但没必要浪费资源),只需要用同一个 Picker,在点击不同 TextField 时切换它的数据源即可。具体步骤如下:
1. 定义数据源和状态变量
首先在你的 ViewController 里定义两个数据源数组,以及用来记录当前点击的 TextField 和当前数据源的变量:
import UIKit class YourViewController: UIViewController { // 你的两个TextField(确保已经通过IBOutlet关联) @IBOutlet weak var jenisIDTextField: UITextField! @IBOutlet weak var provinsiTextField: UITextField! // 对应数据源 let jenisIDArray = ["KTP", "SIM", "Passport", "Kartu Keluarga"] let provinsiArray = ["Jawa Barat", "Jawa Tengah", "Jawa Timur", "Banten"] // 状态变量:记录当前激活的TextField和对应的数据源 private var currentActiveTextField: UITextField? private var currentPickerDataSource: [String] = [] // ... 其他代码 }
2. 初始化Picker并绑定到TextField
在 viewDidLoad 里创建一个共享的 Picker View,把它设置为两个 TextField 的 inputView,同时给 TextField 添加点击事件监听器:
override func viewDidLoad() { super.viewDidLoad() // 创建Picker View let pickerView = UIPickerView() pickerView.dataSource = self pickerView.delegate = self // 给两个TextField设置同一个Picker作为输入视图 jenisIDTextField.inputView = pickerView provinsiTextField.inputView = pickerView // 添加TextField的点击事件(用touchDown更及时捕获点击动作) jenisIDTextField.addTarget(self, action: #selector(textFieldDidTap(_:)), for: .touchDown) provinsiTextField.addTarget(self, action: #selector(textFieldDidTap(_:)), for: .touchDown) // 可选:给Picker添加完成工具栏(方便用户关闭Picker) let toolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: 44)) let doneButton = UIBarButtonItem(title: "Selesai", style: .done, target: self, action: #selector(dismissPicker)) toolBar.items = [UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil), doneButton] jenisIDTextField.inputAccessoryView = toolBar provinsiTextField.inputAccessoryView = toolBar }
3. 处理TextField点击事件,切换数据源
实现点击事件的处理函数,根据当前点击的 TextField 切换 Picker 的数据源,并刷新 Picker:
@objc private func textFieldDidTap(_ textField: UITextField) { currentActiveTextField = textField // 根据点击的TextField切换数据源 if textField == jenisIDTextField { currentPickerDataSource = jenisIDArray } else if textField == provinsiTextField { currentPickerDataSource = provinsiArray } // 必须刷新PickerView,否则数据源切换后不会更新显示内容 textField.inputView?.reloadAllComponents() } // 可选:处理完成按钮的关闭事件 @objc private func dismissPicker() { currentActiveTextField?.resignFirstResponder() }
4. 实现Picker View的数据源和代理方法
让 ViewController 遵守 UIPickerViewDataSource 和 UIPickerViewDelegate 协议,并实现对应的方法:
extension YourViewController: UIPickerViewDataSource, UIPickerViewDelegate { func numberOfComponents(in pickerView: UIPickerView) -> Int { return 1 // 只需要一列 } func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { return currentPickerDataSource.count } func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { return currentPickerDataSource[row] } func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { // 把选中的内容赋值给当前激活的TextField currentActiveTextField?.text = currentPickerDataSource[row] } }
关键注意点
- 一定要在点击 TextField 后调用
reloadAllComponents()刷新 Picker,否则数据源切换后不会更新显示内容 - 用
touchDown事件而不是editingDidBegin,因为前者能更及时地捕获点击动作(避免 TextField 已经处于编辑状态时再次点击不触发的问题) - 如果你的处理函数之前没生效,大概率是没有正确给 TextField 添加事件绑定,或者没有正确切换数据源
内容的提问来源于stack exchange,提问作者Indra Sen
相关产品推荐
相关产品推荐

