Swift中如何在fromDateTf为空时禁用toDateTf的DatePicker交互
iOS日期选择框起始日期优先选择实现方案
问题根源
原有实现存在两个逻辑漏洞:
- 页面首次加载完成后没有初始化
toDateTf的禁用状态,默认是可交互的 doneButtonPressed中先判断起始日期是否为空、再给输入框赋值,导致首次选择起始日期时判断逻辑读取的还是赋值前的空值,需要第二次操作才会触发状态更新
修复步骤
1. 初始化状态控制
在viewDidLoad中完成输入框配置后,直接默认禁用结束日期输入框
2. 修正按钮点击逻辑顺序
先给当前选中的输入框赋值,再根据起始日期的内容控制结束日期的可用状态
3. 可选体验优化
设置结束日期选择器的最小日期为已选的起始日期,避免出现结束日期早于起始日期的异常情况
完整修改后代码
首先修改viewDidLoad部分:
override func viewDidLoad() { super.viewDidLoad() fromDateTf.addInputViewDatePicker(target: self, selector: #selector(doneButtonPressed), tag: 0) toDateTf.addInputViewDatePicker(target: self, selector: #selector(doneButtonPressed), tag: 1) // 新增:初始状态起始日期为空,直接禁用结束日期 toDateTf.isEnabled = false // 可选:设置输入框代理,防止用户手动清空/修改日期内容 fromDateTf.delegate = self toDateTf.delegate = self }
然后修改doneButtonPressed部分:
@objc func doneButtonPressed(_ sender: UIBarButtonItem) { let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd" let dateArr = [fromDateTf, toDateTf] guard let currentTf = dateArr[sender.tag], let picker = currentTf.inputView as? UIDatePicker else { return } // 先给当前输入框赋值 currentTf.text = dateFormatter.string(from: picker.date) currentTf.resignFirstResponder() // 赋值完成后再控制结束日期状态 let fromDateIsEmpty = fromDateTf.text?.isEmpty ?? true toDateTf.isEnabled = !fromDateIsEmpty // 可选优化:选完起始日期后,设置结束日期的最小可选值为起始日期 if sender.tag == 0 { picker.minimumDate = picker.date } }
可选补充:禁止用户手动修改输入框内容(避免手动清空起始日期导致逻辑异常),需要先将控制器遵守的协议从UITextViewDelegate改为UITextFieldDelegate
extension PostServiceRequestVC: UITextFieldDelegate { func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { // 禁止手动输入,只允许通过日期选择器赋值 return false } // 可选:唤起选择器前重置最小日期限制 func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { guard let picker = textField.inputView as? UIDatePicker else { return true } if textField == fromDateTf { picker.minimumDate = Date() } else if textField == toDateTf { let formatter = DateFormatter() formatter.dateFormat = "yyyy-MM-dd" if let fromStr = fromDateTf.text, let fromDate = formatter.date(from: fromStr) { picker.minimumDate = fromDate } } return true } }
内容的提问来源于stack exchange,提问作者SwiftABC
相关产品推荐
相关产品推荐

