UIDatePicker odd behavior when setting minuteInterval
Okay so I was able to change the behavior by explicitly setting the UIDatePicker
date value to the date rounded to the minute interval using the following code:
- (void) handleUIControlEventTouchDown:(id)sender
{
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Set the date picker's minute interval.
NSInteger minuteInterval = [sender tag];
// Setting the date picker's minute interval can change what is selected on
// the date picker's UI to a wrong date, it does not effect the date
// picker's date value.
//
// For example the date picker's date value is 2:31 and then minute interval
// is set to 10. The date value is still 2:31, but 2:10 is selected on the
// UI, not 2:40 (rounded up) or 2:30 (rounded down).
//
// The code that follow's setting the date picker's minute interval
// addresses fixing the date value (and the selected date on the UI display)
// . In the example above both would be 2:30.
datePicker.minuteInterval = minuteInterval;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Calculate the proper date value (and the date to be selected on the UI
// display) by rounding down to the nearest minute interval.
NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:NSMinuteCalendarUnit fromDate:date];
NSInteger minutes = [dateComponents minute];
NSInteger minutesRounded = ( (NSInteger)(minutes / minuteInterval) ) * minuteInterval;
NSDate *roundedDate = [[NSDate alloc] initWithTimeInterval:60.0 * (minutesRounded - minutes) sinceDate:date];
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Set the date picker's value (and the selected date on the UI display) to
// the rounded date.
if ([roundedDate isEqualToDate:datePicker.date])
{
// We need to set the date picker's value to something different than
// the rounded date, because the second call to set the date picker's
// date with the same value is ignored. Which could be bad since the
// call above to set the date picker's minute interval can leave the
// date picker with the wrong selected date (the whole reason why we are
// doing this).
NSDate *diffrentDate = [[NSDate alloc] initWithTimeInterval:60 sinceDate:roundedDate];
datePicker.date = diffrentDate;
[diffrentDate release];
}
datePicker.date = roundedDate;
[roundedDate release];
}
Pay attention to the part where the UIDatePicker
's date is set twice. It was fun figuring that out.
Anyone know how to turn the animation off for the call to minuteInterval
? The phantom scrolling when clicking 5 then 10 is a little unsightly.
UIDatePicker with 5 min interval get date on appear with interval
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!
How to limit date selection on UIDatePicker
Configure your picker with a minuteInterval
datePicker.minuteInterval = 5
will make the picker increment in 5 minute intervals.
You can set the minute interval to whatever interval you need, but the number must evenly divide into 60
UIDatePicker setting incorrect time when configured to use a 30 minute interval
Use NSDateComponents
to get and manipulate the hour and minute of a date. Here's how I did it:
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit) //Need to pass all this so we can get the day right later
fromDate:[NSDate date]];
[components setCalendar:calendar]; //even though you got the components from a calendar, you have to manually set the calendar anyways, I don't know why but it doesn't work otherwise
NSInteger hour = components.hour;
NSInteger minute = components.minute;
//my rounding logic is maybe off a minute or so
if (minute > 45)
{
minute = 0;
hour += 1;
}
else if (minute > 15)
{
minute = 30;
}
else
{
minute = 0;
}
//Now we set the componentns to our rounded values
components.hour = hour;
components.minute = minute;
// Now we get the date back from our modified date components.
NSDate *toNearestHalfHour = [components date];
self.datePicker.date = toNearestHalfHour;
Hope this helps!
Related Topics
Combined Watch Os and iOS Framework
How to Fix Cannot Find 'Firebaseapp' in Scope
How to Create an iOS Liveview in Xcode 8/Swift 3
Enum for Buttonstyle in Swiftui
Swift Cannot Convert The Expression's Type 'Void' to Type 'string!'
Different UIfont Sizes for Different iOS Devices in Swift
Dependency Injection in View Controller
Struct Memberwise Initialization - Omitting Values for Properties That Have Defaults
How to Access to a Static Cell
Views Are Merged Instead of Showing Them Separately
Cannot Convert [Int] to [Int] in Generic Implementation
Horizontal Scrolling in Spritekit (Vs. a Viewcontroller)
Error "[Sharesheet] Connection Invalidated" Error iOS13+ But Not on iOS 11.4