首页 > 代码库 > 使用 UIPickerView 制作的日历

使用 UIPickerView 制作的日历

@implementation CalendarByDicViewController- (void)viewDidLoad{    [super viewDidLoad];        self.view.backgroundColor = [UIColor colorWithRed:0.93 green:0.93 blue:0.93 alpha:1];        UILabel *lab = [[UILabel alloc] initWithFrame:CGRectMake(110, 50, 100, 33)];    lab.text = @"日 历";    lab.textAlignment = NSTextAlignmentCenter;    lab.textColor = [UIColor colorWithRed:155/255.0 green:155/255.0 blue:155/255.0 alpha:1];    lab.font = [UIFont boldSystemFontOfSize:24];    [self.view addSubview:lab];        UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 100, 320, 50)];    pickerView.backgroundColor = [UIColor whiteColor];    [self.view addSubview:pickerView];     pickerView.dataSource = self;    pickerView.delegate = self;        //存储年份的数组    NSMutableArray *yearArray = [[NSMutableArray alloc] initWithCapacity:50];    for (int i = 0; i < 50; i ++)    {        [yearArray addObject:[NSString stringWithFormat:@"%d", START_YEAR + i]];    }    //存储月份的数组    NSMutableArray *monthArray = [[NSMutableArray alloc] initWithCapacity:12];    for (int i = 0; i < 12; i ++)    {        [monthArray addObject:[NSString stringWithFormat:@"%d", i + 1]];    }    //存储天数的数组    NSMutableArray *dayArray = [[NSMutableArray alloc] initWithCapacity:31];    for (int i = 0; i < 31; i ++)    {        [dayArray addObject:[NSString stringWithFormat:@"%d", i + 1]];    }        //将年、月、日都存放进字典    _dataDic = [[NSDictionary alloc] initWithObjectsAndKeys:yearArray, @"year", monthArray, @"month", dayArray, @"day", nil];        //计算今天的日期    NSDate *date = [NSDate date];    date = [date dateByAddingTimeInterval:8 * 60 * 60];    NSString *today = [date description];    int yearNow = [[today substringToIndex:4] intValue];    int monthNow = [[today substringWithRange:NSMakeRange(5, 2)] intValue];    int dayNow = [[today substringWithRange:NSMakeRange(8, 2)] intValue];        //日期指定到今天,让日历默认显示今天的日期    [pickerView selectRow:(yearNow - START_YEAR) inComponent:0 animated:NO];    [pickerView selectRow:(monthNow - 1) inComponent:1 animated:NO];    [pickerView selectRow:(dayNow - 1) inComponent:2 animated:NO];}- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{    return _dataDic.count; //设置选择器的列数,即显示年、月、日三列}- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{    NSArray *keyArray = [_dataDic allKeys];    NSArray *contentArray = [_dataDic objectForKey:keyArray[component]];    //显示每月的天数跟年份和月份都有关系,所以需要判断条件    if (component == 2)    {        int month = [pickerView selectedRowInComponent:1] + 1;        int year = [pickerView selectedRowInComponent:0] + START_YEAR;        switch (month)        {            //每个月的天数不一样            case 4: case 6: case 9: case 11:            {                contentArray = [contentArray subarrayWithRange:NSMakeRange(0, 30)];//4、6、9、11月的天数是30天                return contentArray.count;            }            case 2:            {                if ( [self isLeapYear:year])                {                    //如果是闰年,二月有 29 天                    contentArray = [contentArray subarrayWithRange:NSMakeRange(0, 29)];                }                else                {                    //不是闰年,二月只有 28 天                    contentArray = [contentArray subarrayWithRange:NSMakeRange(0, 28)];                }                                return contentArray.count;            }            default:                return contentArray.count;  //1、3、5、7、8、10、12 月的天数都是31天        }    }    return contentArray.count;  //返回每列的行数}- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component{    return 100; //设置每列的宽度}- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component{    return 50; //设置每行的高度}//设置所在列每行的显示标题,与设置所在列的行数一样,天数的标题设置仍旧需要非一番功夫- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{    NSArray *keyArray = [_dataDic allKeys];    NSArray *contentArray = [_dataDic objectForKey:keyArray[component]];        if (component == 2)    {        int month = [pickerView selectedRowInComponent:1] + 1;        int year = [pickerView selectedRowInComponent:0] +START_YEAR;        switch (month)        {            case 4: case 6: case 9: case 11:            {                contentArray = [contentArray subarrayWithRange:NSMakeRange(0, 30)];                return contentArray[row];            }            case 2:            {                if ( [self isLeapYear:year])                {                    //闰年                    contentArray = [contentArray subarrayWithRange:NSMakeRange(0, 29)];                }                else                {                    contentArray = [contentArray subarrayWithRange:NSMakeRange(0, 28)];                }                                return contentArray[row];            }            default:                return contentArray[row];        }    }    return contentArray[row];}//当选择的行数改变时触发的方法- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{    //第一列的被选择行变化,即年份改变,则刷新月份和天数    if (component == 0)    {        [pickerView reloadAllComponents]; //刷新月份与日期        //下面是将月份和天数都定位到第一行        [pickerView selectRow:0 inComponent:1 animated:YES];        [pickerView selectRow:0 inComponent:2 animated:YES];    }    //第二列的被选择行变化,即月份发生变化,刷新天这列的内容    if (component == 1)    {        [pickerView reloadAllComponents];        [pickerView selectRow:0 inComponent:2 animated:YES];    }//需要这些条件的原因是年份和月份的变化,都会引起每月的天数的变化,他们之间是有联系的,要掌握好他们之间的对应关系}//判断是否闰年- (BOOL)isLeapYear:(int)year{    if ((year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0)))    {        return YES; //是闰年返回 YES    }        return NO; //不是闰年,返回 NO}@end

写这个程序的时候,数组越界的问题快把我给整疯了,回头检查代码的时候一直没找到问题出在哪了,后来重新理了遍思路,其实想法是没错的,估计是来回倒腾就出错了。这时候就需要自己静下心来在重新梳理一遍,大问题没有,这种小错误也是要命的。

代码中用到了字典,也可以直接用数组实现,不过像尝试一下字典,在代码方面也没有简洁多少...

使用 UIPickerView 制作的日历