If I understand correctly, you want to dismiss the current VC when the user selects a date in this state:

But you don't want to do anything if the user changes the month/year in this state:

There is no officially supported way to do this - you are not supposed to use a UIDatePicker
in this way.
I suggest adding an "OK" button or something to that effect, to let the user confirm that they have selected a date. Think about the case of a user mis-taps on the calendar, and end up accidentally dismissing the whole VC. That's quite frustrating if you ask me.
If you really want a behaviour like this, I would suggest making your own date selector.
That said, the month-year selector is, after all, a UIView
, and can be found in the view hierarchy. After some reverse-engineering, that view is called _UICalendarMonthYearSelector
, as of iOS 16.
So theoretically, in selectButtonAction
, you can try to find this view in the hierarchy, and do not dismiss
if you found it. This is heavily subject to changes in the implementation of UIDatePicker
and UICalendarView
. This will probably break in the future.
func findViewInViewHierarchy(root: UIView, target: AnyClass) -> UIView? {
if root.isKind(of: target) {
return root
}
for subview in root.subviews {
if let found = findViewInViewHierarchy(root: subview, target: target) {
return found
}
}
return nil
}
@objc func selectButtonAction() {
// for .compact style date pickers, use presentedViewController.view! as the root
// for .inline style date pickers, use the date picker itself as the root
let monthYearSelector = findViewInViewHierarchy(root: presentedViewController.view!, target: NSClassFromString("_UICalendarMonthYearSelector")!)
if calendar == nil {
// dismiss...
}
}
If you actually wanted to dismiss the pop up that a .compact
style date picker shows, rather than self
, see this answer of mine.