如何判断仅日期模式的inline样式DatePicker当前是日历视图还是年月滚轮视图
方案1:遍历子视图区分当前展示模式
inline模式的UIDatePicker在不同展示状态下,核心子视图类型完全不同:
- 日历视图模式下,子视图树包含
UICalendarView类型的实例 - 年月滚轮模式下,子视图树包含
UIPickerView类型的实例
你可以给UIDatePicker加个扩展方法来判断当前状态:
extension UIDatePicker { var isInCalendarGridView: Bool { func findView(in view: UIView) -> Bool { for subview in view.subviews { let viewClassName = NSStringFromClass(type(of: subview)) if viewClassName == "UICalendarView" { return true } else if viewClassName == "UIPickerView" { return false } if findView(in: subview) { return true } } return false } return findView(in: self) } }
然后在你的回调方法里直接判断即可:
@IBAction func datePickerValueChanged(_ datePicker: UIDatePicker) { guard datePicker.isInCalendarGridView else { // 滚轮模式下直接跳过业务逻辑 return } // 此处写仅点击具体日期需要执行的操作 }
注意:该方案用到了私有类名识别,苹果审核一般不会拦截这类通用UI组件的判断,如果担心风险可使用下方方案二。
方案2:状态标记法(无私有API风险)
由于用户点击顶部年月标题切换视图的操作本身不会触发datePickerValueChanged,你可以通过新增标记变量+点击手势识别的方式实现判断:
- 先定义状态标记变量:
var isCalendarGridMode = true
- 给DatePicker添加点击手势:
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(datePickerTapped(_:))) datePicker.addGestureRecognizer(tapGesture)
- 实现手势回调,识别顶部标题点击动作:
@objc func datePickerTapped(_ gesture: UITapGestureRecognizer) { let location = gesture.location(in: datePicker) // 顶部年月标题区域高度一般在40左右,可根据你的实际布局调整阈值 if location.y < 45 { isCalendarGridMode.toggle() } }
- 最后在值变更回调中判断状态:
@IBAction func datePickerValueChanged(_ datePicker: UIDatePicker) { guard isCalendarGridMode else { return } // 执行你的业务逻辑 }
该方案完全基于公开API实现,不存在审核风险,调整好点击区域阈值即可适配不同布局。
内容的提问来源于stack exchange,提问作者Cheok Yan Cheng
相关产品推荐
相关产品推荐

