I need a UIDatePicker for selecting Month and Year only. I checked the class reference documents. Looks like UIDatePicker is a UIView. I imagined UIPickerView may be a sub view and I can hide the component if I can grab it. But no. That was not possible. Do I have to create my own custom picker then? Any ideas?
Yeah, you probably want to just make your own picker. You don't have to subclass it or anything, though; just use a generic UIPickerView
and return appropriate values from your UIPickerViewDelegate
/UIPickerViewDataSource
methods.
No, this cannot be done using the stock UIDatePicker
.
UIDatePickerModeDate
The date picker displays months, days of the month, and years. The exact order of these items depends on the locale setting. An example of this mode is [ November | 15 | 2007 ].
Source: UIDatePicker class reference
I recommend customizing a UIPickerView
to use two components and populating its rows with month and year symbols retrieved from NSDateFormatter
.
I just reset the day to first of the month when the value change event happens as below. So When the user selects a day, it scrolls back to 1st. I use following for selecting Start date (month & year).
-(void) resetDay {
NSDate *currentDate = [startDatePicker date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *componentsYear = [gregorian components:(NSYearCalendarUnit| NSMonthCalendarUnit) fromDate:currentDate];
NSInteger yearNum = [ componentsYear year];
NSInteger monthNum = [componentsYear month];
NSLog(@"Month %d, Year %d", monthNum, yearNum);
NSDateComponents *componentStartDate = [[NSDateComponents alloc] init];
[componentStartDate setDay:1];
[componentStartDate setMonth:monthNum];
[componentStartDate setYear:yearNum];
NSDate *startDate = [gregorian dateFromComponents:componentStartDate];
[startDatePicker setDate:startDate animated:YES];
[componentStartDate release];
[gregorian release];
}
For selecting the End Date (month & year) it is little bit longer, because I wanted to set the day to 31st or 30th of the month selected.
-(NSInteger) findDaysInYear {
NSDate *currentDate = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *componentsYear = [gregorian components:(NSYearCalendarUnit) fromDate:currentDate];
NSInteger yearNum = [ componentsYear year];
NSDateComponents *componentStartDate = [[NSDateComponents alloc] init];
[componentStartDate setDay:1];
[componentStartDate setMonth:1];
[componentStartDate setYear:yearNum];
NSDate *startDate = [gregorian dateFromComponents:componentStartDate];
NSLog(@"Start date set to %@", startDate);
NSDateComponents *componentEndDate = [[NSDateComponents alloc] init];
[componentEndDate setDay:31];
[componentEndDate setMonth:12];
[componentEndDate setYear:yearNum];
NSDate *endDate = [gregorian dateFromComponents:componentEndDate];
NSLog(@"End date set to %@", endDate);
NSUInteger unitFlags = NSDayCalendarUnit ;
NSDateComponents *componentsDay = [gregorian components:unitFlags fromDate:startDate toDate:endDate options:0];
NSInteger days = [componentsDay day] +1;
NSLog(@"Number of days in the year:%d, is %d", yearNum,days);
[componentEndDate release];
[componentStartDate release];
[gregorian release];
if (days != 365 && days != 366) {
return 366;
}
return days;
}
-(NSInteger) findDaysInMonth:(NSInteger) monthNum {
NSInteger days = 30;
switch (monthNum) {
case 1:
days = 31;
break;
case 2:
if([self findDaysInYear] == 366) days = 29;
else days = 28;
break;
case 3:
days = 31;
break;
case 4:
days = 30;
break;
case 5:
days = 31;
break;
case 6:
days = 30;
break;
case 7:
days = 31;
break;
case 8:
days = 31;
break;
case 9:
days = 30;
break;
case 10:
days = 31;
break;
case 11:
days = 30;
break;
case 12:
days = 31;
break;
default:
break;
}
return days;
}
-(void) resetDay {
NSDate *currentDate = [endDatePicker date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *componentsYear = [gregorian components:(NSYearCalendarUnit| NSMonthCalendarUnit) fromDate:currentDate];
NSInteger yearNum = [ componentsYear year];
NSInteger monthNum = [componentsYear month];
NSDateComponents *componentStartDate = [[NSDateComponents alloc] init];
[componentStartDate setDay:[self findDaysInMonth:monthNum]];
[componentStartDate setMonth:monthNum];
[componentStartDate setYear:yearNum];
NSDate *startDate = [gregorian dateFromComponents:componentStartDate];
[endDatePicker setDate:startDate animated:YES];
[componentStartDate release];
[gregorian release];
}