Swift:UITableView自定义Cell中UITextField绑定UIDatePicker实时更新问题
解决UITableViewCell中UIDatePicker实时更新UITextField的问题
我刚碰到和你一模一样的场景!核心问题在于UIControl的target-action机制不支持传递自定义参数——你写的带两个参数的datePickerValueChanged(caller:destination:)方法根本不会被系统调用,这就是文本框没更新的原因(你能打印Picker的值可能是之前测试过单参数版本?)。下面给你几个实用的解决方案:
方法一:利用Tag关联(最贴合你现有代码)
你已经给TextField和对应的Picker设置了相同的Tag,那直接通过Tag找到目标TextField即可:
- 修改
createPickerView中的action绑定,改成单参数的selector:
func createPickerView(sender: UITextField){ let datePickerView : UIDatePicker = UIDatePicker() datePickerView.datePickerMode = .date sender.inputView = datePickerView datePickerView.tag = sender.tag // 改成单参数的selector datePickerView.addTarget(self, action: #selector(datePickerValueChanged(_:)), for: .valueChanged) }
- 实现单参数的处理方法,通过Tag找到TextField并更新:
@objc func datePickerValueChanged(_ picker: UIDatePicker) { let dateFormatter = DateFormatter() dateFormatter.dateStyle = .medium dateFormatter.timeStyle = .none // 通过Picker的Tag匹配对应的TextField if let targetTextField = view.viewWithTag(picker.tag) as? UITextField { targetTextField.text = dateFormatter.string(from: picker.date) } }
方法二:使用关联对象(更可靠,避免Tag冲突)
如果担心Tag在复杂页面中出现冲突,用Objective-C的关联对象给Picker绑定对应的TextField:
- 先导入Runtime库:
import ObjectiveC
- 定义一个关联对象的唯一Key:
// 全局唯一的关联Key,用于绑定TextField private var AssociatedTextFieldKey: UInt8 = 0
- 在
createPickerView中给Picker绑定TextField:
func createPickerView(sender: UITextField){ let datePickerView : UIDatePicker = UIDatePicker() datePickerView.datePickerMode = .date sender.inputView = datePickerView // 把TextField关联到Picker上 objc_setAssociatedObject(datePickerView, &AssociatedTextFieldKey, sender, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) datePickerView.addTarget(self, action: #selector(datePickerValueChanged(_:)), for: .valueChanged) }
- 在处理方法中取出绑定的TextField:
@objc func datePickerValueChanged(_ picker: UIDatePicker) { let dateFormatter = DateFormatter() dateFormatter.dateStyle = .medium dateFormatter.timeStyle = .none // 取出关联的TextField if let targetTextField = objc_getAssociatedObject(picker, &AssociatedTextFieldKey) as? UITextField { targetTextField.text = dateFormatter.string(from: picker.date) } }
额外修复:Done按钮的方法签名问题
你的dismissKeyboard方法参数是UIButton,但UIBarButtonItem触发的action参数应该是UIBarButtonItem(或者不带参数),修改成这样更稳妥:
@objc func dismissKeyboard() { view.endEditing(true) }
然后在createToolbar中绑定action时改成:
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(dismissKeyboard))
这样修改后,Picker选择时TextField就能实时更新,点击Done也能正常收起键盘啦!
内容的提问来源于stack exchange,提问作者Markussen
相关产品推荐
相关产品推荐

