最近公司提出了一个需求,说是要在程序中加入签到系统。展示的UI要做成日历的形式。日历?懵逼状态中...... 工期给的紧,就想着先看看网上有没有现成的轮子,有的话直接拿来就用。搜了好多,现成的轮子也不少。但是就是没有符合项目需求的呀,如果拿过来改改,又要耗费一些时间。想想,还是自己搞一个吧。说干就干,开始造轮子。
开始造轮子就要思考几个事情:
1.怎么获取每个月的天数?(不会要自己翻月份牌吧,写死在程序吧。)
2.怎么确定每个月1号是星期几?
3.怎么布局UI?(看了网上许多现成的轮子,大部分是for循环创建button按钮,初步的想法是用collectionView实现,这样可以利用cell的复用,避免过多的内存占用)
之前闲着没事看文档的时候,记得苹果有一个日历的类:NSCalendar。这个类对世界上现存的常用的历法进行了封装,提供了不同历法的时间消息,又支持日历计算。
NSCalendar-->日历类,提供了大部分的日期的计算接口,并且允许您在date和NSDateCompents之间转换
NSTimeZone-->时区消息
NSLocale -->本地化信息
NSDate -->表示一个绝对的时间点
NSDateComponents --->一个封装了具体年、月、日、时、分、秒、周、季度等的类
NSDateFormater --->用来在日期和字符串之间转换
解决困惑:
1.怎么获取每个月的天数?
- (NSRange)rangeOfUnit:(NSCalendarUnit)smaller inUnit:(NSCalendarUnit)larger forDate:(NSDate *)date;
这个方法的意思是获取一个小单位在一个大单位里面的取值范围。返回值是NSRange。我们只需要取出这个返回值的长度就是当月的天数。解决!
注解:
(1)当小单位是kCFCalendarUnitDay,大单位是kCFCalendarUnitYear时,并不是取这一年有多少天,而是取“天”这个单位在这一年的取值范围,无论提供的日期是多少,返回的值都是”1--31“。
(2)当小单位是kCFCalendarUnitDay,大单位是kCFCalendarUnitMonth时,返回值是传入时间点所对应月份的天的取值范围。如:传入2月,返回值是1--28,传入3月,返回值是1--31
(3)当小单位是kCFCalendarUnitWeekOfMonth/kCFCalendarUnitWeekOfYear,大单位是kCFCalendarUnitMonth。返回值是传入的时间点所对应的月份,周的取值范围。返回结果受是否设置minimumDaysInFirstWeek属性影响。在默认情况下,取值范围在“1--5”,即一个月包含5周。
(4)当小单位是kCFCalendarUnitDay,大单位是kCFCalendarUnitWeekOfMonth/kCFCalendarUnitWeekOfYear。返回值是周所包含的“天”的取值范围。
2.怎么确定每个月的1号是星期几?
- (NSUInteger)ordinalityOfUnit:(NSCalendarUnit)smaller inUnit:(NSCalendarUnit)larger forDate:(NSDate *)date;
获取一个小单位在一个大单位里面的序数。
注解:
(1)当小单位是kCFCalendarUnitWeekday,大单位是kCFCalendarUnitWeekOfYear/kCFCalendarUnitWeekOfMonth时,即某个日期在这一周是第几天。根据firstWeekday属性不同,返回的结果也不同。具体说明如下:
当 firstWeekday 被指定为星期天(即 =1)时,它返回的值与星期几对应的数值保持一致。比如:
fromDate 传入的参数是星期日,则函数返回1fromDate 传入的参数是星期一,则函数返回2
当 firstWeekday 被指定为其它值时(即 <>1)时,假设firstWeekday 被指定为星期一(即 =2),那么:
fromDate 传入的参数是星期一,则函数返回1
fromDate 传入的参数是星期二,则函数返回2
fromDate 传入的参数是星期日,则函数返回7
(2)当小单位参数为kCFCalendarUnitWeekOfYear/kCFCalendarUnitWeekOfMonth,大单位是kCFCalendarUnitYear时,即表示某个日期在这一年中是第几周。minimumDaysInFirstWeek 属性影响它的返回值
(3)当小单位是kCFCalendarUnitWeekOfYear/kCFCalendarUnitWeekOfMonth,大单位是NSCalendarUnitMonth时,即某个日期是这个月的第几周。minimumDayInFirstWeek属性影响他的返回值。
此处有一个坑:在使用[dateComponents weekday]获取某天对应的星期时,会发现,星期日对应的返回值是1,周一对应的值是2,一次递推,周六对应的值是7.这与我们平时理解的方式不一样。也不能通过设置来改变这种对应关系。iOS中规定的就是周日为1,周一为2,周二为3,周三为4,周四为5,周五为6,周六为7.在使用的时候注意一下这个规则就可以了。
设置firstWeekday之后,获取到的dateComponents.weekOfYear 或 dateComponents.weekOfMonth数据会发生变化。firstWeekday的作用确实是修改当前历法中周的起始位置。但是不可以修改周日对应的数值,只能修改一年获一个月中周的数量,以及周的次序。
3.布局UI
使用大家都常用UICollectionView进行布局。具体代码请参看demo传送门。