iOS Swift中如何判断Inline样式UIDatePicker切换至年月视图?
解决Inline样式UIDatePicker的年月选择状态检测与控制问题
一、判断是否处于年月选择状态
UIDatePicker没有直接提供状态回调,得靠子视图检测或KVO实现:
1. KVO监听子视图变化(最可靠)
Inline模式下,日历视图和年月滚轮是不同的子视图。当用户切换到年月选择时,picker会将子视图替换为UIPickerView,我们可以监听这个变化:
class YourViewController: UIViewController { @IBOutlet weak var datePicker: UIDatePicker! @IBOutlet weak var applyButton: UIButton! override func viewDidLoad() { super.viewDidLoad() datePicker.preferredDatePickerStyle = .inline // 给picker添加KVO监听subviews变化 datePicker.addObserver(self, forKeyPath: "subviews", options: [.new, .old], context: nil) } override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { guard keyPath == "subviews", let picker = object as? UIDatePicker else { return } checkYearMonthMode(picker: picker) } private func checkYearMonthMode(picker: UIDatePicker) { // 子视图中存在UIPickerView,就说明处于年月选择状态 let isInYearMonthMode = picker.subviews.contains { $0 is UIPickerView } applyButton.isEnabled = !isInYearMonthMode } deinit { datePicker.removeObserver(self, forKeyPath: "subviews") } }
2. 结合日期变化回调辅助验证
担心KVO漏触发?可以再加个日期变化的监听,双重验证状态:
// 在viewDidLoad中添加 datePicker.addTarget(self, action: #selector(dateChanged(_:)), for: .valueChanged) @objc private func dateChanged(_ picker: UIDatePicker) { checkYearMonthMode(picker: picker) }
二、强制切回日历视图
要主动退出年月选择状态?直接给picker设置当前选中的日期即可,系统会自动切换回日历视图:
private func switchBackToCalendar() { let currentDate = datePicker.date datePicker.setDate(currentDate, animated: true) }
比如用户点击Cancel按钮时,调用这个方法就能回到日历界面。
三、监听年月切换按钮的点击(有兼容性风险)
如果非要监听左上角的年月按钮点击,可以遍历picker的子视图找到按钮,但注意:苹果可能会修改UI层级,这个方法不是100%稳定:
private func setupYearMonthButtonListener() { func findYearMonthButton(in view: UIView) -> UIButton? { for subview in view.subviews { if let button = subview as? UIButton { // 年月按钮的标题格式为"XXXX年XX月",靠此判断 if button.titleLabel?.text?.contains("年") == true { return button } } if let foundButton = findYearMonthButton(in: subview) { return foundButton } } return nil } if let yearMonthButton = findYearMonthButton(in: datePicker) { yearMonthButton.addTarget(self, action: #selector(yearMonthButtonTapped), for: .touchUpInside) } } @objc private func yearMonthButtonTapped() { // 延迟检查状态,因为视图切换需要时间 DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in self?.checkYearMonthMode(picker: self?.datePicker ?? UIDatePicker()) } }
内容的提问来源于stack exchange,提问作者Muhammad Awais Jamil
相关产品推荐
相关产品推荐

