views:

319

answers:

3

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?

A: 

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.

Noah Witherspoon
+2  A: 

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.

Justin
A: 

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];
}
Gamma-Point