######先說下需求:選擇日期彈出日歷(跟途牛划栓,攜程等差不多就行兑巾。。忠荞。行)
初識(shí)NSCalendar到寫完日歷的感受:
- 懵
- 懵+1
- 什么鬼蒋歌?
- 如此強(qiáng)大的日歷類
- 果然利弊都有,雖然很強(qiáng)大委煤,但是極其耗內(nèi)存
-
一組表情表示寫日歷過程中的心情或者每天的心情(同意的猿/媛點(diǎn)贊):
我的一天.png
先來(lái)點(diǎn)濕的(很濕很能吹...)
NSCalendar官方API:
NSCalendar objects encapsulate information about systems of reckoning time in which the beginning, length, and divisions of a year are defined. They provide information about the calendar and support for calendrical computations such as determining the range of a given calendrical unit and adding units to a given absolute timeNSCalendar的初始化方法:
常用:
// 可指定日歷的算法
NSCalendar * calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
>// currentCalendar取得的值會(huì)一直保持在cache中,第一次取得以后如果用戶修改該系統(tǒng)日歷設(shè)定堂油,這個(gè)值也不會(huì)改變。
NSCalendar * calendar = [NSCalendar currentCalendar];
//如果用autoupdatingCurrentCalendar碧绞,那么每次取得的值都會(huì)是當(dāng)前系統(tǒng)設(shè)置的日歷的值府框。
NSCalendar * autoupdatingCurrent = [NSCalendar autoupdatingCurrentCalendar];
//- initWithCalendarIdentifier:
//如果想要用公歷的時(shí)候,就要將NSDateFormatter的日歷設(shè)置成公歷头遭。否則隨著用戶的系統(tǒng)設(shè)置的改變寓免,取得的日期的格式也會(huì)不一樣。
NSCalendar *initCalendar = [[NSCalendar alloc]initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init] ;
[formatter setCalendar:initCalendar];
NSCalendar官方API翻譯:
NSCalendar對(duì)象封裝了有關(guān)計(jì)算時(shí)間的系統(tǒng)的信息计维,其中定 義了年的開始袜香,長(zhǎng)度和分割。它們提供關(guān)于日歷的信息和對(duì)日歷計(jì)算的支持鲫惶,例如確定給定的日歷單元的范圍和將單位添加到給定的絕對(duì)時(shí)間
由此能理解數(shù)學(xué)英語(yǔ)都辣雞的我看到它有多懵蜈首,NSCalendar功能很強(qiáng)大,還有一點(diǎn)就是我寫完日歷后欠母,界面會(huì)非郴恫撸卡。最終發(fā)現(xiàn)是這個(gè)NSCalendar特別特別耗內(nèi)存赏淌。最好能寫成全局變量來(lái)使用踩寇。
是時(shí)候來(lái)點(diǎn)干的了(聊一些我工作用到的類和一些封裝的方法)
先上效果圖瞅瞅(類似途牛的日歷,沒有選擇后標(biāo)記):
<p>1.獲取當(dāng)前月份有多少天:</p>
-(NSInteger)getCurrentMonthForDays{
// 創(chuàng)建一個(gè)日期類對(duì)象(當(dāng)前月的calendar對(duì)象)
NSCalendar *calendar = [NSCalendar currentCalendar];
// NSRange是一個(gè)結(jié)構(gòu)體六水,其中l(wèi)ocation是一個(gè)以0為開始的index俺孙,length是表示對(duì)象的長(zhǎng)度辣卒。他們都是NSUInteger類型。
NSRange range = [calendar rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:[NSDate date]];
NSUInteger numberOfDaysInMonth = range.length;
return numberOfDaysInMonth;
}
<p>2獲取目標(biāo)月份的天數(shù):</p>
-(NSInteger)getNextNMonthForDays:(NSDate)date
{
NSCalendar * calendar = [NSCalendar currentCalendar];
// 調(diào)用rangeOfUnit方法:(返回一樣是一個(gè)結(jié)構(gòu)體)兩個(gè)參數(shù)一個(gè)大單位睛榄,一個(gè)小單位(.length就是天數(shù)荣茫,.location就是月)
NSInteger monthNum = [calendar rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:date].length;
return monthNum;
}
<p>3.獲取一個(gè)目標(biāo)date(包含某個(gè)月的1號(hào)數(shù)據(jù)),或者說獲取某個(gè)月的1號(hào)的date對(duì)象</p>
-(NSDate *)getAMonthframDate:(NSDate*)date {
// 指定日歷單位场靴,如日期和月份啡莉。(這里指定了年月日,還有其他字段添加單位.特別齊全 :世紀(jì)旨剥,年月日時(shí)分秒等等等)
NSCalendarUnit dayInfoUnits = NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
// NSDateComponents封裝了日期的組件,年月日時(shí)分秒等(個(gè)人感覺像是平時(shí)用的model模型)
NSDateComponents *components = [calendar components: dayInfoUnits fromDate:date];
// 指定1號(hào)
components.day = 1;
// 指定月份(我這里是獲取當(dāng)前月份的下1個(gè)月的1號(hào)的date對(duì)象,所以用的++咧欣,其上個(gè)月或者其他同理)
components.month++;
// 轉(zhuǎn)成需要的date對(duì)象return
NSDate * nextMonthDate =[calendar dateFromComponents:components];
return nextMonthDate;
}
(用到的API基本注釋完了下邊就不那么多注釋了)純屬個(gè)人理解泞边,如發(fā)現(xiàn)錯(cuò)誤的地方請(qǐng)指正该押,大家共同進(jìn)步.
<p>
</p>
<p>4.獲取某個(gè)月的1號(hào)是星期幾(必不可少的一個(gè)方法,用來(lái)布局UI使每月1號(hào)與星期隊(duì)形起來(lái)):</p>
-(NSInteger)getFirstDayWeekForMonth:(NSDate*)date
{
// NSCalendarIdentifierGregorian : 指定日歷的算法
NSCalendar * calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
// NSDateComponents封裝了日期的組件,年月日時(shí)分秒等(個(gè)人感覺像是平時(shí)用的model模型)
// 調(diào)用NSCalendar的components:fromDate:方法返回一個(gè)NSDateComponents對(duì)象
// 需要的參數(shù)分別components:所需要的日期單位 date:目標(biāo)月份的date對(duì)象
NSDateComponents *comps = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond|NSCalendarUnitWeekday fromDate:date];
NSLog(@"NSDateComponents是這個(gè)樣子的:%@",comps);
// 直接調(diào)用自己weekDay屬性
NSInteger weekday = [comps weekday];
#warning mark --找了很多原因不知道為什么星期數(shù)總是比實(shí)際快一天,有時(shí)間找更好的解決方法(暫時(shí)用-1天處理了)
weekday--;
NSLog(@"[comps weekday] = %ld",(long)weekday);
if (weekday == 7) {
return 0;
}else return weekday;
}
<p>5. 當(dāng)前時(shí)間與之前時(shí)間的間隔:</p>
/**
* @author jaki, 15-09-21 17:09:42
* @brief 獲取一個(gè)標(biāo)準(zhǔn)時(shí)間戳與當(dāng)前時(shí)間的時(shí)間差
* @param tinterval 時(shí)間戳
* @return 距離當(dāng)前時(shí)間的時(shí)間間隔
*/
-(NSString *)getStandardTimeInterval:(NSTimeInterval)interval{
//進(jìn)行時(shí)間差比較
//當(dāng)前時(shí)間與1970時(shí)間戳(秒為單位)
NSTimeInterval time = [[NSDate date] timeIntervalSince1970];
// 當(dāng)前時(shí)間戳-當(dāng)時(shí)時(shí)間戳=差值(比如朋友圈動(dòng)態(tài)發(fā)表時(shí)間為10分鐘前(當(dāng)前時(shí)間-發(fā)表時(shí)間))
NSTimeInterval timeInterval = time-interval;
//計(jì)算出天阵谚、小時(shí)、分鐘
int day = timeInterval/(60*60*24);
int hour = ((long)timeInterval%(60*60*24))/(60*60);
int minite = ((long)timeInterval%(60*60*24))%(60*60)/60;
NSMutableString * timeStr = [[NSMutableString alloc]init];
// 邏輯判斷
if (day!=0) {
[timeStr appendString:[NSString stringWithFormat:@"%d天前",day]];
}else{
if (hour!=0) {
[timeStr appendString:[NSString stringWithFormat:@"%d小時(shí)前",hour]];
}else{
if (minite<1) {
[timeStr appendString:@"剛剛"];
}else{
[timeStr appendString:[NSString stringWithFormat:@"%d分鐘前",minite]];
}
}
}
return timeStr;
}
<p>6.獲取當(dāng)前系統(tǒng)時(shí)間:</p>
-(NSString *)getCurrentTime{
NSDateFormatter * formatter = [[NSDateFormatter alloc]init];
<code>// 格式化系統(tǒng)時(shí)間字符串</code>
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSString * time = [formatter stringFromDate:[NSDate date]];
return time;
}
<p>7.返回年月日時(shí)分秒:</p>
<code>#pragma mark --- 對(duì)比上邊就比較簡(jiǎn)單了不過多啰嗦</code>
-(int)getYear{
NSCalendar *calendar = [NSCalendar currentCalendar];
NSUInteger unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
NSDateComponents *dateComponent = [calendar components:unitFlags fromDate:self];
return (int)dateComponent.year;
}
-(int)getMonth{
NSCalendar *calendar = [NSCalendar currentCalendar];
NSUInteger unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
NSDateComponents *dateComponent = [calendar components:unitFlags fromDate:self];
return (int)dateComponent.month;
}
-(int)getDay{
NSCalendar *calendar = [NSCalendar currentCalendar];
NSUInteger unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
NSDateComponents *dateComponent = [calendar components:unitFlags fromDate:self];
return (int)dateComponent.day;
}
-(int)getHour{
NSCalendar *calendar = [NSCalendar currentCalendar];
NSUInteger unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
NSDateComponents *dateComponent = [calendar components:unitFlags fromDate:self];
return (int)dateComponent.hour;
}
-(int)getMinute{
NSCalendar *calendar = [NSCalendar currentCalendar];
NSUInteger unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
NSDateComponents *dateComponent = [calendar components:unitFlags fromDate:self];
return (int)dateComponent.minute;
}
-(int)getSecond{
NSCalendar *calendar = [NSCalendar currentCalendar];
NSUInteger unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
NSDateComponents *dateComponent = [calendar components:unitFlags fromDate:self];
return (int)dateComponent.second;
}
<p>8.date對(duì)象NSString互相轉(zhuǎn)換:</p>
// date對(duì)象轉(zhuǎn)換成字符串(最后return根據(jù)自己需求處理)
-(NSString * )theTargetDateConversionStr:(NSDate * )date
{
NSDateFormatter* dateFormat = [[NSDateFormatter alloc] init];//實(shí)例化一個(gè)NSDateFormatter對(duì)象
[dateFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss"];//設(shè)定時(shí)間格式,這里可以設(shè)置成自己需要的格式
NSString *currentDateStr = [dateFormat stringFromDate:date];
// 根據(jù)自己需求處理字符串
return [currentDateStr substringToIndex:7];
}
// NSString對(duì)象轉(zhuǎn)date
-(NSDate* )theTargetStringConversionDate:(NSString *)str
{
//設(shè)置轉(zhuǎn)換格式
NSDateFormatter *formatter = [[NSDateFormatter alloc] init] ;
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSDate *date=[formatter dateFromString:str];
return date;
}
8個(gè)方法差不多能夠?qū)崿F(xiàn)一個(gè)簡(jiǎn)單點(diǎn)的日歷控件了烟具,88大發(fā),大功告成梢什。2017第一篇,比較偏基礎(chǔ)適合我這種菜鳥或者新手朝聋,大神路過的話就當(dāng)娛樂一下了嗡午。有錯(cuò)誤的話希望多多指點(diǎn)樓主一下
下面貼一下代碼以及實(shí)現(xiàn)思路:
思路:
剛知道要寫日歷的時(shí)候是懵逼的,對(duì)NSdate還好冀痕、NSCalendar完全沒有概念荔睹。查了挺多資料,也在github找了好幾個(gè)demo想直接拿過來(lái)用言蛇,不過不太合適所以決定自己寫僻他。試了tableView、跟colelctionView,最后選擇collectionView需求是展示當(dāng)前月跟之后三個(gè)月的日歷腊尚。
所以就:
區(qū)頭實(shí)現(xiàn)星期View->四個(gè)分區(qū)->區(qū)頭區(qū)尾配合實(shí)現(xiàn)效果吨拗,上邊聊得幾個(gè)方法處理DataSource.
日歷中標(biāo)記今天的思路是:
實(shí)例變量selectedIndex(今天的下標(biāo)): ---實(shí)現(xiàn)->(獲取到今天幾號(hào),加上今天周幾-1就是日歷中今天那個(gè)cell所在的位置了)
直接截圖代碼:
都比較基礎(chǔ)(自己保存下筆記婿斥,也分享給能用到的童鞋)
UICollectionView實(shí)現(xiàn):
DataSource:每個(gè)分區(qū)返回item數(shù)量
DataSource: 繪制item
DataSource:headerView和footerView以及點(diǎn)擊回傳數(shù)據(jù):