简体   繁体   中英

UIDatePicker set Maximum date

I am using this code to block the user from going over the limit I set:

in view did load:

NSDate *Date=[NSDate date];
[DatePickerForDate setMinimumDate:Date];
[DatePickerForDate setMaximumDate:[Date dateByAddingTimeInterval: 63072000]]; //time interval in seconds

And this method:

- (IBAction)datePickerChanged:(id)sender{
if ( [DatePickerForDate.date timeIntervalSinceNow ] < 0 ){
    NSDate *Date=[NSDate date];
    DatePickerForDate.date = Date;
}

if ( [DatePickerForDate.date timeIntervalSinceNow ] > 63072000){
    NSDate *Date=[NSDate date];
    DatePickerForDate.date = Date;
}
}

The first part works (the one with <0), and returns to the current date, but the one > 63072000, sometimes works and sometimes doesn't. By the way 63072000 is about 2 years. Any ideas?

I experimented using a UIDatePicker with a maximumDate of one month from now:

NSDate* now = [NSDate date] ;
// Get current NSDate without seconds & milliseconds, so that I can better compare the chosen date to the minimum & maximum dates.
NSCalendar* calendar = [NSCalendar currentCalendar] ;
NSDateComponents* nowWithoutSecondsComponents = [calendar components:(NSEraCalendarUnit|NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit) fromDate:now] ;
NSDate* nowWithoutSeconds = [calendar dateFromComponents:nowWithoutSecondsComponents] ;
//  UIDatePicker* picker ;
picker.minimumDate = nowWithoutSeconds ;

NSDateComponents* addOneMonthComponents = [NSDateComponents new] ;
addOneMonthComponents.month = 1 ;
NSDate* oneMonthFromNowWithoutSeconds = [calendar dateByAddingComponents:addOneMonthComponents toDate:nowWithoutSeconds options:0] ;
picker.maximumDate = oneMonthFromNowWithoutSeconds ;

I found that:

  • The first time you attempt to select a date outside of the minimum and maximum range, the UIDatePicker will scroll itself back "in range".
  • If you immediately select a date out of range again, the Picker will not scroll back, allowing you to select a date out of range.
  • If the Picker's selected date is out of range, its date property will return the nearest date that's in range.
  • When you call setDate: or setDate:animated: , if the date you pass is the exact same date returned by the Picker's date property, the Picker will do nothing.

With that in mind, here is a method that you can call when the Picker's value changes that prevents you from ever selecting a date out of range:

- (IBAction) datePickerChanged:(id)sender {
    // When `setDate:` is called, if the passed date argument exactly matches the Picker's date property's value, the Picker will do nothing. So, offset the passed date argument by one second, ensuring the Picker scrolls every time.
    NSDate* oneSecondAfterPickersDate = [picker.date dateByAddingTimeInterval:1] ;
    if ( [picker.date compare:picker.minimumDate] == NSOrderedSame ) {
        NSLog(@"date is at or below the minimum") ;
        picker.date = oneSecondAfterPickersDate ;
    }
    else if ( [picker.date compare:picker.maximumDate] == NSOrderedSame ) {
        NSLog(@"date is at or above the maximum") ;
        picker.date = oneSecondAfterPickersDate ;
    }
}

The above if and else if sections are nearly identical, but I kept them separate so that I could see the different NSLogs, and also to better debug.

Here's the working project on GitHub.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM