如何在未选择日期时重置内联iOS UIDatePicker



使用新的内联UIDatePicker(在iOS 14中引入(时。在未选择日期的情况下,如何将日历重置为当前日期。

运行以下操作时,当您选择另一个日期时,显示的日历将重置为当前日期:

self.datePicker.setDate(Date(), animated: true)

但是,如果创建一个新的内联UIDatePicker并开始滚动月份,则在用户选择特定日期之前,运行同一行代码不会更新视图。

这很奇怪。。。

我的猜测是,当使用较老的";"轮子";日期选择器样式,轮子停止滚动时会选择一个新日期。。。没有办法";滚动离开";从所选日期开始。

我的第二个猜测是,这个问题可能会在未来的iOS更新中得到改变("修复"(。

无论如何,这里有一个工作。。。

  • 获取今天的日期
  • 从选取器获取所选日期
  • 如果它们相同,用户可能已经滚动了月份/年份,所以
    • 将一天添加到";今天">
    • 将选择器设置为"0";明天";(已设置动画(
    • 进行异步调用以将选择器设置为"0";今天">
  • 如果日期相同,只需将选择器设置为";今天";(已设置动画(

我只做了一个快速测试,所以你需要彻底测试它。可能还需要添加一些额外的检查——比如当选择器显示时,如果日历在午夜滚动会发生什么;如果";今天";是一个月的最后一天;等

// get "today" date
let today = Date()
// get selected date
let pickerDate = self.datePicker.date

// are the dates the same day?
let todayIsSelected = Calendar.current.isDate(today, inSameDayAs:pickerDate)
if todayIsSelected {
// picker has today selected, but may have scrolled months...
// should never fail, but this unwraps the optional
guard let nextDay = Calendar.current.date(byAdding: .day, value: 1, to: today) else {
return
}
// animate to "tomorrow"
self.datePicker.setDate(nextDay, animated: true)
// async call to animate to "today"
DispatchQueue.main.async {
self.datePicker.setDate(today, animated: true)
}
} else {
// picker has a different date selected
//  so just animate to "today"
self.datePicker.setDate(today, animated: true)
}


编辑-完整示例:

class ScratchVC: UIViewController {

let datePicker = UIDatePicker()
let btn = UIButton()

override func viewDidLoad() {
super.viewDidLoad()

if #available(iOS 14.0, *) {
datePicker.preferredDatePickerStyle = .inline
} else {
// Fallback on earlier versions
}

btn.backgroundColor = .red
btn.setTitle("Go To Today", for: [])
btn.setTitleColor(.white, for: .normal)
btn.setTitleColor(.gray, for: .highlighted)

btn.translatesAutoresizingMaskIntoConstraints = false
datePicker.translatesAutoresizingMaskIntoConstraints = false

view.addSubview(btn)
view.addSubview(datePicker)

let g = view.safeAreaLayoutGuide

NSLayoutConstraint.activate([

btn.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
btn.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 40.0),
btn.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -40.0),

datePicker.widthAnchor.constraint(equalTo: g.widthAnchor, multiplier: 0.9),
datePicker.centerXAnchor.constraint(equalTo: g.centerXAnchor),
datePicker.centerYAnchor.constraint(equalTo: g.centerYAnchor),

])

btn.addTarget(self, action: #selector(didTap(_:)), for: .touchUpInside)

}

@objc func didTap(_ sender: Any) {

// get "today" date
let today = Date()
// get selected date
let pickerDate = self.datePicker.date

// are the dates the same day?
let todayIsSelected = Calendar.current.isDate(today, inSameDayAs:pickerDate)
if todayIsSelected {
// picker has today selected, but may have scrolled months...
// should never fail, but this unwraps the optional
guard let nextDay = Calendar.current.date(byAdding: .day, value: 1, to: today) else {
return
}
// animate to "tomorrow"
self.datePicker.setDate(nextDay, animated: true)
// async call to animate to "today" - delay for 0.1 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1, execute: {
self.datePicker.setDate(today, animated: true)
})
} else {
// picker has a different date selected
//  so just animate to "today"
self.datePicker.setDate(today, animated: true)
}

}

}

最新更新