Search code examples
iosobjective-cuipickerview

Custom datepicker with UIPickerView first day of the month is always monday


I need to create a custom datepicker where first column shows day name, day number and second column shows month name and year.

enter image description here

Current month works great but for every other month first day of month is always monday.

#pragma Pickerview

-(void)initilazePickerview
{

    //set our picker array data 
    self.yearAndMonth = [[NSMutableArray alloc] init];
    self.day= [[NSMutableArray alloc] init];
    self.backendYearAndMonth= [[NSMutableArray alloc] init];
    self.backendDay= [[NSMutableArray alloc] init];

    /*
     next 12 months after current month
     */

    NSDateFormatter  *dateFormatter   = [[NSDateFormatter alloc] init];
    NSDate           *today           = [NSDate date];
    NSCalendar       *currentCalendar = [NSCalendar currentCalendar];

    NSDateComponents *monthComponents = [currentCalendar components:NSMonthCalendarUnit fromDate:today];
    int currentMonth = [monthComponents month];

    NSDateComponents *yearComponents  = [currentCalendar components:NSYearCalendarUnit  fromDate:today];
    int currentYear  = [yearComponents year];
    int nextYear     = currentYear + 1;

    int months  = 1;
    int year;
    for(int m = currentMonth-1; months <= 12; m++){

        int nextMonth = m % 12;

        if(nextMonth < currentMonth-1){
            year = nextYear;
        } else {
            year = currentYear;
        }

        //NSLog(@"%@ %i",[[dateFormatter shortMonthSymbols] objectAtIndex: nextMonth],year);
        NSString *populateYearAndMonth=[NSString stringWithFormat:@"%@   %i",[[dateFormatter shortMonthSymbols] objectAtIndex: nextMonth],year];
        [self.yearAndMonth addObject:populateYearAndMonth];

        //save year and month in array
        NSMutableDictionary *saveYearMonth= [[NSMutableDictionary alloc] init];
        [saveYearMonth setObject:[NSNumber numberWithInt:nextMonth] forKey:@"month"];
        [saveYearMonth setObject:[NSNumber numberWithInt:year] forKey:@"year"];
        [self.backendYearAndMonth addObject:saveYearMonth];

        months++;
    }
    [self populateDays:currentMonth-1 year:currentYear];

}
-(void) populateDays:(int) populateMonth year:(int) populateYear
{

    NSDateFormatter  *dateFormatter   = [[NSDateFormatter alloc] init];
    NSDate           *today           = [NSDate date];
    NSCalendar       *currentCalendar = [NSCalendar currentCalendar];

    NSDateComponents *monthComponents = [currentCalendar components:NSMonthCalendarUnit fromDate:today];
    int currentMonth = [monthComponents month];


    if (populateMonth==currentMonth-1) {
        NSLog(@"Today");
        [self.day addObject:@"Today"];
        [self.backendDay addObject:today];

        NSRange days = [currentCalendar rangeOfUnit:NSDayCalendarUnit
                               inUnit:NSMonthCalendarUnit
                              forDate:today];
        NSLog(@"days.length = %i",days.length);


        NSDateComponents *dayComponents = [currentCalendar components:NSDayCalendarUnit fromDate:today];
        int currentDay = [dayComponents day];

        for (int i=currentDay+1; i<=days.length; i++) {
            int daySymbol=i%7;
            NSString *populateDay=[NSString stringWithFormat:@"%@   %i",[[dateFormatter shortWeekdaySymbols] objectAtIndex: daySymbol],i];
            [self.day addObject:populateDay];

        }

    }
    else
    {
        NSDateComponents* comps = [[NSDateComponents alloc] init];

        // Set your month here
        [comps setMonth:populateMonth+1];

        NSRange days = [currentCalendar rangeOfUnit:NSDayCalendarUnit
                                             inUnit:NSMonthCalendarUnit
                                            forDate:[currentCalendar dateFromComponents:comps]];
        NSLog(@"days.length = %i",days.length);


        NSDateComponents *dayComponents = [currentCalendar components:NSDayCalendarUnit fromDate:[currentCalendar dateFromComponents:comps]];
        int currentDay = [dayComponents day];

        for (int i=currentDay; i<=days.length; i++) {
            int daySymbol=i%7;
            NSString *populateDay=[NSString stringWithFormat:@"%@   %i",[[dateFormatter shortWeekdaySymbols] objectAtIndex: daySymbol],i];
            [self.day addObject:populateDay];

        }


    }

     [self.myCustomPicker reloadComponent:0];
}
    - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {

    if (component == 1)
    {
        [self.day removeAllObjects];
        [self.backendDay removeAllObjects];
        NSDictionary *dataDict= [self.backendYearAndMonth objectAtIndex:row];
        int month=[[dataDict objectForKey:@"month"]intValue];
        int year=[[dataDict objectForKey:@"year"]intValue];
        [self populateDays:month year:year];

    }
}
// returns the number of 'columns' to display.
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{

    NSInteger result = 0;
    if ([pickerView isEqual:self.myCustomPicker]){
        result = 2;
    }
    return result;
}

// returns the number of rows in each component..
- (NSInteger)pickerView:(UIPickerView *)pickerView
numberOfRowsInComponent:(NSInteger)component{

    NSInteger result = 0;
    if ([pickerView isEqual:self.myCustomPicker]){
        switch (component) {
            case 0:
                result = [self.day count];
                break;
            case 1:
                result = [self.yearAndMonth count];
                break;

            default:
                break;
        }
    }
    return result;

}

//return a plain NSString to display the row for the component.
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row
            forComponent:(NSInteger)component{
    NSString *result = nil;
    if ([pickerView isEqual:self.myCustomPicker]){
        switch (component) {
            case 0:
                result = [self.day objectAtIndex:row];
                break;
            case 1:
                result = [self.yearAndMonth objectAtIndex:row];
                break;

            default:
                break;
        }

    }
    return result;
}

Any advise to get around this problem? Thanks Space,


Solution

  • I end up getting first day of the month from calendar and built to month on it, not the best solution but it works

    -(void) populateDays:(int) populateMonth year:(int) populateYear
    {
    
        NSDateFormatter  *dateFormatter   = [[NSDateFormatter alloc] init];
        NSDate           *today           = [NSDate date];
        NSCalendar       *currentCalendar = [NSCalendar currentCalendar];
    
        NSDateComponents *monthComponents = [currentCalendar components:NSMonthCalendarUnit fromDate:today];
        int currentMonth = [monthComponents month];
    
    
        if (populateMonth==currentMonth-1) {
            NSLog(@"Today");
            [self.day addObject:@"Today"];
            [self.backendDay removeAllObjects];
            [self.backendDay addObject:today];
    
            NSRange days = [currentCalendar rangeOfUnit:NSDayCalendarUnit
                                   inUnit:NSMonthCalendarUnit
                                  forDate:today];
            NSLog(@"days.length = %i",days.length);
    
    
            NSDateComponents *dayComponents = [currentCalendar components:NSDayCalendarUnit fromDate:today];
            int currentDay = [dayComponents day];
    
            for (int i=currentDay+1; i<=days.length; i++) {
                int daySymbol=i%7;
                NSString *populateDay=[NSString stringWithFormat:@"%@   %i",[[dateFormatter shortWeekdaySymbols] objectAtIndex: daySymbol],i];
                [self.day addObject:populateDay];
    
                NSString *dateString =[NSString stringWithFormat:@"%d-%d-%d",populateYear,populateMonth+1,i];
                NSLog(@"dateString %@",dateString);
                NSDateFormatter *dateFormatterForLoop = [[NSDateFormatter alloc] init];
                // this is imporant - we set our input date format to match our input string
                // if format doesn't match you'll get nil from your string, so be careful
                [dateFormatterForLoop setDateFormat:@"yyyy-MM-dd"];
                NSDate *dateFromString = [[NSDate alloc] init];
                // voila!
                dateFromString = [dateFormatterForLoop dateFromString:dateString];
                NSLog(@"dateFromString %@",dateFromString);
                //asdsadadd
                [self.backendDay addObject:dateFromString];
    
            }
    
        }
        else
        {
    
            // Set your month here
            [monthComponents setMonth:populateMonth+1];
    
            NSRange days = [currentCalendar rangeOfUnit:NSDayCalendarUnit
                                                 inUnit:NSMonthCalendarUnit
                                                forDate:[currentCalendar dateFromComponents:monthComponents]];
            NSLog(@"days.length = %i",days.length);
    
    
            NSString *dateString =[NSString stringWithFormat:@"%d-%d-01",populateYear,populateMonth+1];
            NSLog(@"dateString %@",dateString);
            NSDateFormatter *dateFormatterForLoop = [[NSDateFormatter alloc] init];
            [dateFormatterForLoop setTimeStyle:NSDateFormatterNoStyle];
            [dateFormatterForLoop setDateFormat:@"yyyy-MM-dd"];
            NSDate *dateFromString = [[NSDate alloc] init];
            dateFromString = [dateFormatterForLoop dateFromString:dateString];
    
            //NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
            NSDateComponents *comps = [currentCalendar components:NSWeekdayCalendarUnit fromDate:dateFromString];
            int weekday = [comps weekday];
            NSLog(@"First Day is %i",weekday);
    
            [self.backendDay removeAllObjects];
            for (int i=1; i<=days.length; i++) {
    
                int daySymbol=(i+weekday-2)%7;
                NSString *populateDay=[NSString stringWithFormat:@"%@   %i",[[dateFormatter shortWeekdaySymbols] objectAtIndex: daySymbol],i];
                [self.day addObject:populateDay];
    
                NSString *dateStringBack =[NSString stringWithFormat:@"%d-%d-%d",populateYear,populateMonth+1,i];
                NSLog(@"dateStringBack %@",dateStringBack);
                NSDateFormatter *dateFormatterForLoopBack = [[NSDateFormatter alloc] init];
                [dateFormatterForLoopBack setTimeStyle:NSDateFormatterNoStyle];
                [dateFormatterForLoopBack setDateFormat:@"yyyy-MM-dd"];
                NSDate *dateFromStringBack = [[NSDate alloc] init];
                dateFromStringBack = [dateFormatterForLoopBack dateFromString:dateStringBack];
                [self.backendDay addObject:dateFromStringBack];
            }
    
    
        }
    
         [self.myCustomPicker reloadComponent:0];
    }