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

太長時間沒有寫文章了,最近幾個月一直忙找工作的事情,現在終于塵埃落定,于是又從OC的坑掉進了swift的坑里,不過大家不要擔心,樓主是不會丟棄掉OC的,這篇文章也是針對OC于swift區別來寫的,說出來一把辛酸淚。不說了,直接進入正題吧。
這次的文章不做日歷的詳細介紹,因為是其本身已經封裝好的,這次只是針對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
    }

計算當前月份天數

//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
}

計算指定月天數

//OC版本
- (NSInteger)getDaysInMonthWithYearAndMonth:(NSInteger)year month:(NSInteger)month{
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.dateFormat = @"yyyy-MM";
    
    //這里視具體情況而定,如果日期帶有前綴0的可不要,我這里是傳入了單數字日期
    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這么個東西,開始查閱別人用的日歷用到這個玩意兒的時候一臉懵逼不知道是什么東西,后來專門查閱了下這個屬性也沒有人做解釋,于是只好自己去官方文檔上查閱,在查閱完成后原諒我自己英語不太好,翻譯為中文之后也大概沒有懂什么意思,只是知其一二,現在給大家貼上,英文就是官方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對象指定的組件應該遞增,并在溢出時循環為零/ 1,但不應導致更高的單位增加。

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

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對象中指定的下一個最高單位的下一個實例的結束之前沒有匹配的時間時,此方法使用缺少單元的下一個現有值并保留較低單位的值。

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對象中指定的下一個最高單位的下一個實例的結束之前沒有匹配的時間時,此方法使用缺少單元的下一個現有值,并且不保留較低單位的值。

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

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

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容