问题
I have spent about 3 hours trying to get a UIDatePicker
to do what I want it to do. I have it setup as an action of a UITextField
to segue to a new view controller with a UIDatePicker
. This is all working. I have been able to select a date and send it back to the original view controller.
The problem is that I am using 5 minute time intervals. If I don't move the date picker "wheels" and select my done button to return to the parent controller the non-interval time is returned. So 11:37 returns 11:37 when I need 11:40. However, if I change the "wheels" it returns the rounded time. The datepicker is currently showing the 5 minute intervals on appear. Any clues to lead me to the right solution? I have tried setDate
and minuteInterval
on the UIDatePicker
on viewDidAppear to no avail. Below is the code I have been using:
protocol DatePickerDelegate {
func datePickerDidSelect(selectedDate: String)
}
class DatePickerVC: UIViewController {
@IBOutlet weak var pickerView: UIDatePicker!
var selectedDate = ""
var delegate : DatePickerDelegate?
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
//setDate()
//Have tried using setDate and minuteInterval here
}
func formatDate() -> DateFormatter {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM d, yyyy h:mm a"
return dateFormatter
}
func setDate() {
let dateFormatter = formatDate()
selectedDate = dateFormatter.string(from: pickerView.date)
self.delegate?.datePickerDidSelect(selectedDate: selectedDate)
print(selectedDate)
}
@IBAction func datePickerChanged(_ sender: Any) {
setDate()
}
@IBAction func doneBtnPressed(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
}
@IBAction func cancelBtnPressed(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
}
}
回答1:
you could check the date and round it to your needs like this:
override func viewDidLoad() {
super.viewDidLoad()
let calendar = Calendar.current
var dateComponents = calendar.dateComponents([.month, .day, .year, .hour, .minute], from: datePicker.date)
guard var hour = dateComponents.hour, var minute = dateComponents.minute else {
print("something went wrong")
return
}
let intervalRemainder = minute % datePicker.minuteInterval
if intervalRemainder > 0 {
// need to correct the date
minute += datePicker.minuteInterval - intervalRemainder
if minute >= 60 {
hour += 1
minute -= 60
}
// update datecomponents
dateComponents.hour = hour
dateComponents.minute = minute
// get the corrected date
guard let roundedDate = calendar.date(from: dateComponents) else {
print("something went wrong")
return
}
// update the datepicker
datePicker.date = roundedDate
}
}
feel free to ask if anything is unclear!
回答2:
Another alternative is to create an extension that allows you to tweak intervals on the date value that's set when the UIDatePicker
is initialized.
extension Date {
var nearest30Min: Date {
var dateComponents = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute], from: self)
guard let hours = dateComponents.hour else { return self }
switch dateComponents.minute ?? 0 {
case 0...14:
dateComponents.minute = 0
case 15...44:
dateComponents.minute = 30
case 44...59:
dateComponents.minute = 0
dateComponents.hour = hours + 1
default:
break
}
return dateComponents.date ?? self
}
}
After your UIDatePicker
is initialized, you could update the datePicker's
value with the following code:
datePicker.setDate(datePicker.date.nearest30min, animated: false)
来源:https://stackoverflow.com/questions/41536519/uidatepicker-with-5-min-interval-get-date-on-appear-with-interval