This article talks about the development of date picker ideas
The following figure shows the deadline picker
Develop a selector, just two points
1. Data source
Data sources are divided into, how many columns, how many columns, what content each one presents
- How many bar
// 3 column func numberOfComponents(in pickerView: UIPickerView) -> Int {return 3}Copy the code
- How many in a column
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { switch component { case 0: // yearinfo.cnt case 1: // yearinfo.cnt case 1: // yearinfo.cnt case 1: // yearinfo.cnt default: // 2 // dayinfo.cnt}}Copy the code
- What each item presents
func pickerView(_ pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? { switch component { case 0: // if row == registerx. year{// Select registerx. year Return yearInfo[row]. Selected} else{// return yearInfo[row]. Normal} case 1: yearInfo[row]. Month {return monthInfo[row]. Selected} else{return monthInfo[row]. Normal} default: Day {return dayInfo[row]. Selected} else{return dayInfo[row]. Normal}}Copy the code
2. Change the data source
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { }
Copy the code
Obviously, the number of days of each month is different, modify the month, the date is also changed
You need to calculate how many days there are in a month
To count days, you need years and months
Points in a leap year
func dayNum(inMonth m: Int, inYear y: Int) -> Int{ var isrunNian = false if y % 4 == 0{ if y % 100 == 0{ isrunNian = (y % 400 == 0) } else{ isrunNian = true } } switch m{ case 1, 3, 5, 7, 8, 10, 12: return 31 case 4, 6, 9, 11: return 30 default: if isrunNian{ return 29 } else{ return 28 } } }Copy the code
Development, deadline picker
Is to put some restrictions on the data source,
Start with a specific date (today)
Design data structure:
In the information
Year information, the corresponding data structure, is relatively simple
- Because years can determine months, for example, from May 2022 to 2021
Today is 20210729, there is no May, so the time of month needs to be updated
- The year could also determine the date, for example, from February 29, 2024, to 2023
From leap years to ordinary years, February has only 28 days,
So the time of day should be updated
- Months and days do not affect years
Need to find this year
Struct YearX {// let yearInfo: [Int] // let yearInfo: [Int] // let yearInfo: [Int] Int init(){ minYEAR = { () -> Int in let formatter = DateFormatter() formatter.dateFormat = "yyyy" let time = formatter.string(from: Date()) if let t = Int(time){ return t } else{ return 2021 } }() yearInfo = Array(minYEAR... 2030) cnt = yearInfo.count } }Copy the code
On the information
The message of the month, which is relatively simple,
Several components in two groups
-
Full month, 1 to 12
-
The month of this year,
Does not include past months
struct MonthX { let minMonth: Int var monthInfo: [Int] var cnt: Int{ monthInfo.count } init(){ minMonth = { let formatter = DateFormatter() formatter.dateFormat = "MM" let time = formatter.string(from: Date()) if let t = Int(time){ return t } else{ return 7 } }() monthInfo = Array(minMonth... Mutating func reset(){monthInfo = Array(1... Mutating func beCurrent(){monthInfo = Array(minMonth){monthInfo = Array(minMonth... 12)}}Copy the code
Message of the day
To calculate the date, record the currently selected year and month
struct DayX { let minDay: Int var dayInfo: [Int]! Var jahr: Int var moon: Int var CNT: Int{dayinfo.count} var final: Int{dayNum(inMonth: moon, inYear: jahr) } init(jahr y: Int, month m: Int) { jahr = y moon = m minDay = { let formatter = DateFormatter() formatter.dateFormat = "dd" let time = formatter.string(from: Date()) if let t = Int(time){ return t } else{ return 28 } }() dayInfo = Array(minDay... Final)} /// // mutating func reset(month m: Int){moon = m dayInfo = Array(1... Final)} // Mutating func reset(jahr y: Int, month m: Int){ jahr = y moon = m dayInfo = Array(1... // mutating beCurrent from minDay to beCurrent(month m: Int){ moon = m dayInfo = Array(minDay... Final)} // Mutating func beCurrent(jahr y: Int, month m: Int){ jahr = y moon = m dayInfo = Array(minDay... final) } }Copy the code
Added: Modify the data source
You need to make a note of the year, month and day that were previously selected
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { switch component { case 0: // Modify year, The month also changed registerX. Year = row. PickerView reloadComponent (0) if the row = = 0 {monthInfo. BeCurrent ()} else {monthInfo. Reset ()} registerX.month = min(monthInfo.cnt - 1, registerX.month) pickerView.reloadComponent(1) let lunar = monthInfo[registerX.month].scalar if row == 0, registerX.month == 0{ dayInfo.beCurrent(jahr: yearInfo[0].scalar, month: lunar) } else{ dayInfo.reset(jahr: yearInfo[row].scalar, month: Lunar)} registerX. Day = min (dayInfo. CNT - 1, registerX. Day / / to leap year pickerView reloadComponent (2) case 1: RegisterX / / modify month. The month = row. PickerView reloadComponent. (1) if registerX year = = 0, row = = 0 {dayInfo. BeCurrent (the month: monthInfo[0].scalar) } else{ dayInfo.reset(month: monthInfo[row].scalar) } registerX.day = min(dayInfo.cnt - 1, registerX.day) pickerView.reloadComponent(2) default: / / / / modify day 2 registerX. Day = row. PickerView reloadComponent (2)}}Copy the code