IOS 开发笔记——做日历开发的总结

来源:互联网 发布:超牛数据恢复手机版 编辑:程序博客网 时间:2024/06/07 02:24

做日历开发中经常要用到的一个类是NSCalendar,作者通常要用到他来获取年月日甚至是某个月有多少天这种需求,今天作者为大家讲解一个最简单的日历表,初学者都能看懂的,那么,我们开始吧

在做日历之前我们要分清楚以下的几个需求:
1.分析这个月的第一天是第一周的星期几
2.分析这个月有多少天

那么好了,我们一开始当然需要知道这个月的第一天是星期几才能说得上是一个月历嘛,所以我们要把星期日到星期一的 label 都创建出来

 // weekday NSArray *array = @[@"周日",@"周一",@"周二",@"周三",@"周四",@"周五",@"周六"];UIView *weekBg = [[UIView alloc]init];weekBg.frame = CGRectMake(0, CGRectGetMaxY(headlabel.frame), self.frame.size.width, itemH);[self addSubview:weekBg];

这就是我们首先要显示这一周的周期表了,哈哈


好了,当然,我们也需要到创建这周一到周日 个按钮,这些按钮用来显示周一~ 周日的label 了

    for (int i = 0; i < array.count; i ++) {        UILabel *label = [[UILabel alloc]init];        label.text = array[i];        label.font = [UIFont systemFontOfSize:14];        label.textColor = [UIColor redColor];        label.frame = CGRectMake(itemW * i, 0, itemW, itemH);        label.textAlignment = NSTextAlignmentCenter;        [weekBg addSubview:label];    }

那么,日期的7个 label 算是创建好了,但是他们还没有显示任何东西,那么我们当然需要知道,这个月的第一天是星期几,才能确定数字1的位置是在那个 lable 上面了,那么如何获取呢,我们就需要到NSCalendar这个类了

给我一个日期,这个方法能算出这个月的第一天,是星期几了

- (NSInteger)firstWeekdayInThisMotnth:(NSDate *)date{    NSCalendar *calendar = [NSCalendar currentCalendar]; // 取得当前用户的逻辑日历(logical calendar)    [calendar setFirstWeekday:1]; //  设定每周的第一天从星期几开始,比如:. 如需设定从星期日开始,则value传入1 ,如需设定从星期一开始,则value传入2 ,以此类推    NSDateComponents *comp = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:date];    [comp setDay:1]; // 设置为这个月的第一天    NSDate *firstDayOfMonthDate = [calendar dateFromComponents:comp];    NSUInteger firstWeekday = [calendar ordinalityOfUnit:NSCalendarUnitWeekday inUnit:NSCalendarUnitWeekOfMonth forDate:firstDayOfMonthDate]; // 这个月第一天在当前日历的顺序    // 返回某个特定时间(date)其对应的小的时间单元(smaller)在大的时间单元(larger)中的顺序    return firstWeekday - 1;}

好了,我们终于知道这个月的第一天,也就是数字1应该显示在什么地方了,但是,我们也需要知道这个月究竟有多少天,因为每个月的天数都是不同的嘛

给我一个日期,我就能显示出这个月的长度了

- (NSInteger)totaldaysInMonth:(NSDate *)date{    NSRange daysInOfMonth = [[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:date]; // 返回某个特定时间(date)其对应的小的时间单元(smaller)在大的时间单元(larger)中的范围    return daysInOfMonth.length;}

接下来当然运用这两个方法了

// 1.分析这个月的第一天是第一周的星期几NSInteger firstWeekday = [self firstWeekdayInThisMotnth:date];// 2.分析这个月有多少天NSInteger dayInThisMonth = [self totaldaysInMonth:date];

好了,有了1号的位置,和这个月的长度,前提条件都有了,接下来就是创建可爱的日历了

 for (int i = 0; i < 42; i ++) {        UIButton *button = [[UIButton alloc] init];        button.titleLabel.font = [UIFont systemFontOfSize:14];        [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];        [self addSubview:button];        int x = (i % 7) * itemW ;        int y = (i / 7) * itemH + CGRectGetMaxY(weekBg.frame);        button.frame = CGRectMake(x, y, itemW, itemH);        NSInteger day = 0;        if (i < firstWeekday) {            //            day = dayInLastMonth - firstWeekday + i + 1;            continue;        }else if (i > firstWeekday + dayInThisMonth - 1){            //            day = i + 1 - firstWeekday - dayInThisMonth;            continue;        }else{            day = i - firstWeekday + 1;        }        [button setTitle:[NSString stringWithFormat:@"%d",(int)day] forState:UIControlStateNormal];

好了,最简单的日历算是完成了

以下附上我做日历时候经常用到的方法和注意点

- (NSInteger)firstWeekdayInThisMotnth:(NSDate *)date{    NSCalendar *calendar = [NSCalendar currentCalendar]; // 取得当前用户的逻辑日历(logical calendar)    [calendar setFirstWeekday:1]; //  设定每周的第一天从星期几开始,比如:. 如需设定从星期日开始,则value传入1 ,如需设定从星期一开始,则value传入2 ,以此类推    NSDateComponents *comp = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:date];    [comp setDay:1]; // 设置为这个月的第一天    NSDate *firstDayOfMonthDate = [calendar dateFromComponents:comp];    NSUInteger firstWeekday = [calendar ordinalityOfUnit:NSCalendarUnitWeekday inUnit:NSCalendarUnitWeekOfMonth forDate:firstDayOfMonthDate]; // 这个月第一天在当前日历的顺序    // 返回某个特定时间(date)其对应的小的时间单元(smaller)在大的时间单元(larger)中的顺序    return firstWeekday - 1;}// 获取日历月份的长度,也就是这个月有多少天- (NSInteger)totaldaysInMonth:(NSDate *)date{    NSRange daysInOfMonth = [[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:date]; // 返回某个特定时间(date)其对应的小的时间单元(smaller)在大的时间单元(larger)中的范围    return daysInOfMonth.length;}// 日历的上一个月- (NSDate *)lastMonth:(NSDate *)date{    NSDateComponents *comp = [[NSDateComponents alloc]init];    comp.month = -1;    NSDate *newDate = [[NSCalendar currentCalendar] dateByAddingComponents:comp toDate:date options:0];    return newDate;}// 获取日历的年份- (NSInteger)year:(NSDate *)date{    NSDateComponents *components = [[NSCalendar currentCalendar] components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:date];    return [components year];}// 获取日历的月份- (NSInteger)month:(NSDate *)date{    NSDateComponents *components = [[NSCalendar currentCalendar] components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:date];    return [components month];}// 获取日历的为第几天- (NSInteger)day:(NSDate *)date{    NSDateComponents *components = [[NSCalendar currentCalendar] components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:date];    return [components day];}

在设置 NSDate 的时候用 formatter 转换 日期会发生实际日期比转换日期多了一天的现象,这个是由于时区的影响,如果出现这种情况,可以用以下方法解决

NSDateFormatter *formatter = [[NSDateFormatter alloc]init];[formatter setDateFormat:@ "yyyy-MM-dd"];NSTimeZone *GTMZone = [NSTimeZone timeZoneForSecondsFromGMT:0];[formatter setTimeZone:GTMZone]; NSString *dateStr = [NSString stringWithFormat:@"%d-%d-%d",(int)self.components.year,(int)self.components.month,(int)self.components.day];NSDate *date = [formatter dateFromString:dateStr];

如何将 NSDate 转换成日期组件NSDateComponents

NSDate *date = [NSDate date];NSDateComponents *components = [[NSCalendar currentCalendar] components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:date];
别问我为什么知道这么多,因为我吃过亏。。。。
0 0
原创粉丝点击