最近公司提出了一個(gè)需求,說是要在程序中加入簽到系統(tǒng)。展示的UI要做成日歷的形式。日歷?懵逼狀態(tài)中...... ? ?工期給的緊,就想著先看看網(wǎng)上有沒有現(xiàn)成的輪子,有的話直接拿來就用。搜了好多,現(xiàn)成的輪子也不少。但是就是沒有符合項(xiàng)目需求的呀,如果拿過來改改,又要耗費(fèi)一些時(shí)間。想想,還是自己搞一個(gè)吧。說干就干,開始造輪子。
開始造輪子就要思考幾個(gè)事情:
1.怎么獲取每個(gè)月的天數(shù)?(不會(huì)要自己翻月份牌吧,寫死在程序吧。)
2.怎么確定每個(gè)月1號是星期幾?
3.怎么布局UI?(看了網(wǎng)上許多現(xiàn)成的輪子,大部分是for循環(huán)創(chuàng)建button按鈕,初步的想法是用collectionView實(shí)現(xiàn),這樣可以利用cell的復(fù)用,避免過多的內(nèi)存占用)
之前閑著沒事看文檔的時(shí)候,記得蘋果有一個(gè)日歷的類:NSCalendar。這個(gè)類對世界上現(xiàn)存的常用的歷法進(jìn)行了封裝,提供了不同歷法的時(shí)間消息,又支持日歷計(jì)算。
NSCalendar-->日歷類,提供了大部分的日期的計(jì)算接口,并且允許您在date和NSDateCompents之間轉(zhuǎn)換
NSTimeZone-->時(shí)區(qū)消息
NSLocale ? ? -->本地化信息
NSDate ? ? ? ?-->表示一個(gè)絕對的時(shí)間點(diǎn)
NSDateComponents --->一個(gè)封裝了具體年、月、日、時(shí)、分、秒、周、季度等的類
NSDateFormater --->用來在日期和字符串之間轉(zhuǎn)換
解決困惑:
1.怎么獲取每個(gè)月的天數(shù)?
- (NSRange)rangeOfUnit:(NSCalendarUnit)smaller inUnit:(NSCalendarUnit)larger forDate:(NSDate *)date;
這個(gè)方法的意思是獲取一個(gè)小單位在一個(gè)大單位里面的取值范圍。返回值是NSRange。我們只需要取出這個(gè)返回值的長度就是當(dāng)月的天數(shù)。解決!
注解:
(1)當(dāng)小單位是kCFCalendarUnitDay,大單位是kCFCalendarUnitYear時(shí),并不是取這一年有多少天,而是取“天”這個(gè)單位在這一年的取值范圍,無論提供的日期是多少,返回的值都是”1--31“。
(2)當(dāng)小單位是kCFCalendarUnitDay,大單位是kCFCalendarUnitMonth時(shí),返回值是傳入時(shí)間點(diǎn)所對應(yīng)月份的天的取值范圍。如:傳入2月,返回值是1--28,傳入3月,返回值是1--31
(3)當(dāng)小單位是kCFCalendarUnitWeekOfMonth/kCFCalendarUnitWeekOfYear,大單位是kCFCalendarUnitMonth。返回值是傳入的時(shí)間點(diǎn)所對應(yīng)的月份,周的取值范圍。返回結(jié)果受是否設(shè)置minimumDaysInFirstWeek屬性影響。在默認(rèn)情況下,取值范圍在“1--5”,即一個(gè)月包含5周。
(4)當(dāng)小單位是kCFCalendarUnitDay,大單位是kCFCalendarUnitWeekOfMonth/kCFCalendarUnitWeekOfYear。返回值是周所包含的“天”的取值范圍。
2.怎么確定每個(gè)月的1號是星期幾?
- (NSUInteger)ordinalityOfUnit:(NSCalendarUnit)smaller inUnit:(NSCalendarUnit)larger forDate:(NSDate *)date;
獲取一個(gè)小單位在一個(gè)大單位里面的序數(shù)。
注解:
(1)當(dāng)小單位是kCFCalendarUnitWeekday,大單位是kCFCalendarUnitWeekOfYear/kCFCalendarUnitWeekOfMonth時(shí),即某個(gè)日期在這一周是第幾天。根據(jù)firstWeekday屬性不同,返回的結(jié)果也不同。具體說明如下:
當(dāng) firstWeekday 被指定為星期天(即 =1)時(shí),它返回的值與星期幾對應(yīng)的數(shù)值保持一致。比如:
fromDate 傳入的參數(shù)是星期日,則函數(shù)返回1fromDate 傳入的參數(shù)是星期一,則函數(shù)返回2
當(dāng) firstWeekday 被指定為其它值時(shí)(即 <>1)時(shí),假設(shè)firstWeekday 被指定為星期一(即 =2),那么:
fromDate 傳入的參數(shù)是星期一,則函數(shù)返回1
fromDate 傳入的參數(shù)是星期二,則函數(shù)返回2
fromDate 傳入的參數(shù)是星期日,則函數(shù)返回7
(2)當(dāng)小單位參數(shù)為kCFCalendarUnitWeekOfYear/kCFCalendarUnitWeekOfMonth,大單位是kCFCalendarUnitYear時(shí),即表示某個(gè)日期在這一年中是第幾周。minimumDaysInFirstWeek 屬性影響它的返回值
(3)當(dāng)小單位是kCFCalendarUnitWeekOfYear/kCFCalendarUnitWeekOfMonth,大單位是NSCalendarUnitMonth時(shí),即某個(gè)日期是這個(gè)月的第幾周。minimumDayInFirstWeek屬性影響他的返回值。
此處有一個(gè)坑:在使用[dateComponents weekday]獲取某天對應(yīng)的星期時(shí),會(huì)發(fā)現(xiàn),星期日對應(yīng)的返回值是1,周一對應(yīng)的值是2,一次遞推,周六對應(yīng)的值是7.這與我們平時(shí)理解的方式不一樣。也不能通過設(shè)置來改變這種對應(yīng)關(guān)系。iOS中規(guī)定的就是周日為1,周一為2,周二為3,周三為4,周四為5,周五為6,周六為7.在使用的時(shí)候注意一下這個(gè)規(guī)則就可以了。
設(shè)置firstWeekday之后,獲取到的dateComponents.weekOfYear 或 dateComponents.weekOfMonth數(shù)據(jù)會(huì)發(fā)生變化。firstWeekday的作用確實(shí)是修改當(dāng)前歷法中周的起始位置。但是不可以修改周日對應(yīng)的數(shù)值,只能修改一年獲一個(gè)月中周的數(shù)量,以及周的次序。
3.布局UI
使用大家都常用UICollectionView進(jìn)行布局。具體代碼請參看demo傳送門。