自定義日歷彈窗視圖-OC與swift版本

太長時間沒有寫文章了译柏,最近幾個月一直忙找工作的事情,現(xiàn)在終于塵埃落定奈搜,于是又從OC的坑掉進了swift的坑里悉盆,不過大家不要擔心,樓主是不會丟棄掉OC的媚污,這篇文章也是針對OC于swift區(qū)別來寫的,說出來一把辛酸淚舀瓢。不說了,直接進入正題吧耗美。
這次的文章不做日歷的詳細介紹京髓,因為是其本身已經封裝好的,這次只是針對swift日歷的具體用法做一個介紹商架,直接上代碼堰怨。
首先先看一下效果圖:

Calendar.png

可以自動翻頁,萬年歷蛇摸,可以選中日期回傳
這里寫的日歷主要用了NSCalendar這個API备图,對應的swift用的Calendar,這里的話先介紹一下官方API是怎么解釋NSCalendar的:
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 time
經過一番谷歌翻譯后:
NSCalendar對象封裝了關于一年的開始赶袄,長度和分割定義的推算時間的信息揽涮。 它們提供有關日歷的信息,并支持日歷計算饿肺,例如確定給定的日歷單位的范圍蒋困,并將單位添加到給定的絕對時間
多的不需要太多的介紹,直接看用法吧:

首先是計算當前日期或選擇的日期是幾號

//OC版本
-(NSInteger)dayWithDate:(NSDate *)date{
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *component = [calendar components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:date];
    return component.day;
}
//swift版本
func day(date : Date) -> NSInteger {
        let calendar = Calendar.current
        let componentsSet = Set<Calendar.Component>([.year, .month, .day,])
        var componentss = calendar.dateComponents(componentsSet, from: date)
        return componentss.day!
    }

這里要注意的是敬辣,swift不能像OC直接使用NSCalendarUnit單位并且用單目運算符連接雪标,而是需要用Set對象承載起來使用Set對象,同理這里返回的是日子溉跃,而返回月和年只需要改為month和year即可村刨。

計算每個月1號對應周幾

//OC版本
- (NSInteger)firstWeekDayInThisMonthWithDate:(NSDate *)date{
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *component = [calendar components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:date];

    calendar.firstWeekday = 1;
    component.day = 1;
    
    NSDate *firstDate = [calendar dateFromComponents:component];
    return [calendar ordinalityOfUnit:NSCalendarUnitWeekday inUnit:NSCalendarUnitWeekOfMonth forDate:firstDate] - 1;
}
//swift版本
func firstWeekDayInThisMonth(date : Date) -> NSInteger {
        var calendar = Calendar.current
        let componentsSet = Set<Calendar.Component>([.year, .month, .day,])
        var componentss = calendar.dateComponents(componentsSet, from: date)
        
        calendar.firstWeekday = 1
        componentss.day = 1
        let first = calendar.date(from: componentss)
        let firstWeekDay = calendar.ordinality(of: .weekday, in: .weekOfMonth, for: first!)
        
        return firstWeekDay! - 1
    }

計算當前月份天數(shù)

//OC版本
- (NSInteger)totalDaysInThisMonthWithDate:(NSDate *)date{
    return [[NSCalendar currentCalendar]rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:date].length;
}
//swift版本
 func totalDaysInThisMonth(date : Date) -> NSInteger {
        let totalDays : Range = Calendar.current.range(of: .day, in: .month, for: date)!
        return totalDays.count
}

計算指定月天數(shù)

//OC版本
- (NSInteger)getDaysInMonthWithYearAndMonth:(NSInteger)year month:(NSInteger)month{
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.dateFormat = @"yyyy-MM";
    
    //這里視具體情況而定,如果日期帶有前綴0的可不要,我這里是傳入了單數(shù)字日期
    NSString *monthStr = @"";
    if (month < 10) {
        monthStr = [NSString stringWithFormat:@"0%ld",month];
    }else{
        monthStr = [NSString stringWithFormat:@"%ld",month];
    }
    
    NSString *dateStr = [NSString stringWithFormat:@"%ld-%@",year,monthStr];
    NSDate *date = [dateFormatter dateFromString:dateStr];
    //NSCalendarIdentifierGregorian公歷日歷的意思
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
    return [calendar rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:date].length;
}
//swift版本
func getDaysInMonth( year: Int, month: Int) -> Int{
        let dateFor = DateFormatter.init()
        dateFor.dateFormat = "yyyy-MM"
        
        var monthStr = ""
        if month < 10 {
            monthStr = "0" + String(month)
        }else{
            monthStr = String(month)
        }
        
        let dateStr = String(year) + "-" + monthStr
        let date = dateFor.date(from: dateStr)
        let calenDar = Calendar.init(identifier: Calendar.Identifier.gregorian)
        let totaldays : Range = calenDar.range(of: .day, in: .month, for: date!)!
        
        return totaldays.count
    }

//這里的這個id字段NSCalendarIdentifierGregorian是公歷的意思撰茎,其余的可以通過官方文檔查閱

上一個月

//OC版本
- (NSDate *)nextMonthWithDate:(NSDate *)date{
    NSDateComponents *component = [[NSDateComponents alloc] init];
    component.month = -1;
    return [[NSCalendar currentCalendar]dateByAddingComponents:component toDate:date options:NSCalendarMatchStrictly];
}
//swift版本
 func lastMonth(date : Date) -> Date {
        var dateComponents = DateComponents.init()
        dateComponents.month = -1
        let newDate = Calendar.current.date(byAdding: dateComponents, to: date)
        return newDate!
    }

這里說一下OC的那個options的屬性嵌牺,swift沒有用到。這里OC使用的是NSCalendarMatchStrictly這么個東西,開始查閱別人用的日歷用到這個玩意兒的時候一臉懵逼不知道是什么東西髓梅,后來專門查閱了下這個屬性也沒有人做解釋拟蜻,于是只好自己去官方文檔上查閱,在查閱完成后原諒我自己英語不太好枯饿,翻譯為中文之后也大概沒有懂什么意思酝锅,只是知其一二,現(xiàn)在給大家貼上,英文就是官方API原文奢方,中文當然就是是翻譯過來的意思了搔扁,具體應用可以視自己情況而定:

NSCalendarWrapComponents
Specifies that the components specified for an NSDateComponents object should be incremented and wrap around to zero/one on overflow, but should not cause higher units to be incremented.
指定為NSDateComponents對象指定的組件應該遞增,并在溢出時循環(huán)為零/ 1蟋字,但不應導致更高的單位增加稿蹲。

NSCalendarMatchStrictly
Specifies that the operation should travel as far forward or backward as necessary looking for a match.
指定操作應該根據(jù)需要前進或后退,尋找匹配鹊奖。

NSCalendarSearchBackwards
Specifies that the operation should travel backwards to find the previous match before the given date.
指定操作向后移動以在給定日期之前找到先前的匹配苛聘。

NSCalendarMatchPreviousTimePreservingSmallerUnits
Specifies that, when there is no matching time before the end of the next instance of the next highest unit specified in the given NSDateComponents object, this method uses the previous existing value of the missing unit and preserves the lower units' values.
指定當在給定的NSDateComponents對象中指定的下一個最高單位的下一個實例的結束之前沒有匹配的時間時,此方法使用缺失單元的先前存在的值忠聚,并保留較低單位的值设哗。

NSCalendarMatchNextTimePreservingSmallerUnits
Specifies that, when there is no matching time before the end of the next instance of the next highest unit specified in the given NSDateComponents object, this method uses the next existing value of the missing unit and preserves the lower units' values.
指定當在給定的NSDateComponents對象中指定的下一個最高單位的下一個實例的結束之前沒有匹配的時間時,此方法使用缺少單元的下一個現(xiàn)有值并保留較低單位的值两蟀。

NSCalendarMatchNextTime
Specifies that, when there is no matching time before the end of the next instance of the next highest unit specified in the given NSDateComponents object, this method uses the next existing value of the missing unit and does not preserve the lower units' values.
指定當在給定的NSDateComponents對象中指定的下一個最高單位的下一個實例的結束之前沒有匹配的時間時网梢,此方法使用缺少單元的下一個現(xiàn)有值,并且不保留較低單位的值赂毯。

NSCalendarMatchFirst
Specifies that, if there are two or more matching times, the operation should return the first occurrence.
指定如果有兩個或更多匹配的時間战虏,操作應該返回第一個出現(xiàn)的。

NSCalendarMatchLast
Specifies that, if there are two or more matching times, the operation should return the last occurrence.
指定如果有兩個或更多匹配的時間党涕,則操作應返回最后一次出現(xiàn)的烦感。

好了,基本代碼介紹完畢膛堤,日歷主體是使用collectionView實現(xiàn)的啸盏,中間如果有不好的地方或者大家有改進的地方歡迎評論去留言討論。
下面給上代碼地址:
OC版本:https://github.com/Archerry/Calendar_OC
swift版本:https://github.com/Archerry/Calendar_swift

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末骑祟,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子气笙,更是在濱河造成了極大的恐慌次企,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件潜圃,死亡現(xiàn)場離奇詭異缸棵,居然都是意外死亡,警方通過查閱死者的電腦和手機谭期,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進店門堵第,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吧凉,“玉大人,你說我怎么就攤上這事踏志》保” “怎么了?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵针余,是天一觀的道長饲鄙。 經常有香客問我,道長圆雁,這世上最難降的妖魔是什么忍级? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮伪朽,結果婚禮上轴咱,老公的妹妹穿的比我還像新娘。我一直安慰自己烈涮,他們只是感情好朴肺,可當我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著跃脊,像睡著了一般宇挫。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上酪术,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天器瘪,我揣著相機與錄音,去河邊找鬼绘雁。 笑死橡疼,一個胖子當著我的面吹牛,可吹牛的內容都是我干的庐舟。 我是一名探鬼主播欣除,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼挪略!你這毒婦竟也來了历帚?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤杠娱,失蹤者是張志新(化名)和其女友劉穎挽牢,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體摊求,經...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡禽拔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片睹栖。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡硫惕,死狀恐怖,靈堂內的尸體忽然破棺而出野来,到底是詐尸還是另有隱情恼除,我是刑警寧澤,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布梁只,位于F島的核電站缚柳,受9級特大地震影響,放射性物質發(fā)生泄漏搪锣。R本人自食惡果不足惜秋忙,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望构舟。 院中可真熱鬧灰追,春花似錦、人聲如沸狗超。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽努咐。三九已至苦蒿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間渗稍,已是汗流浹背佩迟。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留竿屹,地道東北人报强。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像拱燃,于是被迫代替她去往敵國和親秉溉。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,678評論 2 354

推薦閱讀更多精彩內容