100行代码swift从零实现一个iOS日历

首先实现日历最重要的是数据,UI的话大家可以自己实现,demo中有简单的日历实现,有了数据源不论是使用UIKit还是swiftUI都非常简单 iOS开发的时候很多时候会用到日历组件,很多时候网上的三方库实在臃肿,其实我们可以快速实现一个

代码如下

ini 复制代码
let tool = CalendarTool(start: "2025-04-01", startWeek: .sunday)
// 数组里面就是 2025-04-01 月份数据(包含上个月和下个月补齐部分)
let arr = tool.getDaysInMonthArr()

源码如下,如果需要更多功能可以自己修改

github.com/AblerSong/S...

ini 复制代码
//(sunday = 1,monday = 2,...)
enum Weekday: Int {
    case sunday = 1, monday, tuesday, wednesday, thursday, friday, saturday
}

class CalendarModel {
    init(date: Date, type: Int = 0) {
        self.date = date
        self.type = type
    }
    
    // pre: -1; current: 0; next: 1
    let type: Int
    // date
    let date: Date
    // yyyy-MM-dd
    private lazy var dateString: String = {
        CalendarTool.dateFormatter.string(from: date)
    }()
    private lazy var dateArr = dateString.components(separatedBy: "-").map{ Int($0)! }
    
    private lazy var chineseDateString: String = {
        CalendarTool.chineseDateFormatter.string(from: date)
    }()
    private lazy var chineseDateArr = chineseDateString.components(separatedBy: "-")
    
    // yyyy
    lazy var year = dateArr[0]
    // MM
    lazy var month = dateArr[1]
    // dd
    lazy var day = dateArr[2]
    
    lazy var chineseMonth = {
        let str = chineseDateArr[1]
        if str.hasPrefix("闰") {
            return "闰" + CalendarTool.chineseMonths[Int(str.dropFirst())! - 1]
        }
        return CalendarTool.chineseMonths[Int(str)! - 1]
    }()
    
    lazy var chineseDay = {
        CalendarTool.chineseDays[Int(chineseDateArr[2])! - 1]
    }()
}

class CalendarTool {
    /// init
    /// - Parameters:
    ///   - startString: start date string yyyy-MM-dd
    ///   - startWeek: default:  sunday
    init(start: String, startWeek: Weekday = .sunday) {
        self.startString = start
        self.startWeek = startWeek.rawValue
    }
    
    func getDaysInMonthArr() -> [CalendarModel] {
        guard let startDate = dateFormatter.date(from: startString),
              let endDate = calendar.date(byAdding:.month, value: 1, to: startDate) else {
            return []
        }
        
        var dateArray: [CalendarModel] = []
        
        var currentDate = startDate;
        
        {
            var arr: [CalendarModel] = []
            var week = calendar.dateComponents([.weekday], from: currentDate).weekday
            while week != startWeek {
                currentDate = calendar.date(byAdding:.day, value: -1, to: currentDate)!
                arr.append(CalendarModel(date: currentDate, type: -1))
                week = calendar.dateComponents([.weekday], from: currentDate).weekday
            }
            dateArray = Array(arr.reversed())
        }()
        
        currentDate = startDate
        while currentDate < endDate {
            dateArray.append(CalendarModel(date: currentDate))
            currentDate = calendar.date(byAdding:.day, value: 1, to: currentDate)!
        }
        
        {
            var week = calendar.dateComponents([.weekday], from: currentDate).weekday
            while week != startWeek {
                dateArray.append(CalendarModel(date: currentDate, type: 1))
                currentDate = calendar.date(byAdding:.day, value: 1, to: currentDate)!
                week = calendar.dateComponents([.weekday], from: currentDate).weekday
            }
        }()
        return dateArray
    }
    
    private var dateFormatter: DateFormatter { CalendarTool.dateFormatter }
    
    private var chineseDateFormatter: DateFormatter { CalendarTool.chineseDateFormatter }
    
    private var calendar: Calendar { CalendarTool.calendar }
    
    private  let startWeek: Int
    
    private let startString: String
    
    static let dateFormatter = {
        // Lock down the East Eighth Time Zone and 24 - hour format; modify it yourself if needed.
        let dateFormatter = DateFormatter()
        dateFormatter.calendar = Calendar(identifier:.iso8601)
        dateFormatter.locale = Locale(identifier: "zh_CN")
        dateFormatter.timeZone = TimeZone(identifier: "Asia/Shanghai")
        dateFormatter.dateFormat = "yyyy-MM-dd"
        return dateFormatter
    }()
    
    static let chineseDateFormatter = {
        // Lock down the East Eighth Time Zone and 24 - hour format; modify it yourself if needed.
        let dateFormatter = DateFormatter()
        dateFormatter.calendar = Calendar(identifier: .chinese)
        dateFormatter.locale = Locale(identifier: "zh_CN")
        dateFormatter.timeZone = TimeZone(identifier: "Asia/Shanghai")
        dateFormatter.dateFormat = "yyyy-MM-dd"
        return dateFormatter
    }()
    
    private static let calendar = Calendar(identifier:.iso8601)
    
    static let chineseMonths = ["正月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "冬月", "腊月"]
    
    static let chineseDays = ["初一", "初二", "初三", "初四", "初五", "初六", "初七", "初八", "初九", "初十", "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十", "廿一", "廿二", "廿三", "廿四", "廿五", "廿六", "廿七", "廿八", "廿九", "三十"]
    
}
相关推荐
幸福回头13 小时前
ms-swift 代码推理数据集
llm·swift
若水无华1 天前
fiddler 配置ios手机代理调试
ios·智能手机·fiddler
不二狗1 天前
每日算法 -【Swift 算法】Two Sum 问题:从暴力解法到最优解法的演进
开发语言·算法·swift
Aress"1 天前
【ios越狱包安装失败?uniapp导出ipa文件如何安装到苹果手机】苹果IOS直接安装IPA文件
ios·uni-app·ipa安装
Jouzzy1 天前
【iOS安全】Dopamine越狱 iPhone X iOS 16.6 (20G75) | 解决Jailbreak failed with error
安全·ios·iphone
瓜子三百克1 天前
采用sherpa-onnx 实现 ios语音唤起的调研
macos·ios·cocoa
左钦杨1 天前
IOS CSS3 right transformX 动画卡顿 回弹
前端·ios·css3
努力成为包租婆2 天前
SDK does not contain ‘libarclite‘ at the path
ios
安和昂2 天前
【iOS】Tagged Pointer
macos·ios·cocoa
I烟雨云渊T3 天前
iOS 阅后即焚功能的实现
macos·ios·cocoa