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 = ["初一", "初二", "初三", "初四", "初五", "初六", "初七", "初八", "初九", "初十", "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十", "廿一", "廿二", "廿三", "廿四", "廿五", "廿六", "廿七", "廿八", "廿九", "三十"]
    
}
相关推荐
随笔记1 小时前
uniapp开发的小程序输入框在ios自动填充密码,如何欺骗苹果手机不让自动填充
前端·ios·app
unicrom_深圳市由你创科技2 小时前
Unity开发如何解决iOS闪退问题
unity·ios·蓝桥杯
TE-茶叶蛋2 小时前
iOS打包流程
ios
大熊猫侯佩3 小时前
Swift 数学计算:用 Accelerate 框架让性能“加速吃鸡”
算法·swift
大熊猫侯佩3 小时前
Swift 6.2 并发江湖:两大神功破局旧制,代码运行经脉革新(下)
swiftui·swift·wwdc
大熊猫侯佩3 小时前
Swift 6.2 并发江湖:两大神功破局旧制,代码运行经脉革新(上)
swiftui·swift·wwdc
大熊猫侯佩3 小时前
SwiftUI 7 江湖新风:WWDC25 揭晓神秘武林志
swiftui·swift·wwdc
大熊猫侯佩3 小时前
SwiftUI 7(iOS 26 / iPadOS 26)中玻璃化标签页的全新玩法
swiftui·swift·apple
Daniel_Coder4 小时前
iOS Widget 开发-1:什么是 iOS Widget?开发前的基本认知
ios·swiftui·swift·widget