[Swift5] DatePicker for years only

Let's make a DatePicker only for the year and month

This is the first article! I created it because I wanted to be able to use the DatePicker only for the year and month by tapping the textField. There are many things that I still don't understand If you have any suggestions for improvement, I would appreciate it if you could comment. ٩ ('ω') و

environment

・ Swift 5.3 ・ Xcode 12.1

Source code

  1. Create MonthYearPickerView class

import UIKit

class MonthYearPickerView: UIPickerView, UIPickerViewDelegate, UIPickerViewDataSource{
   
    var months: [String]!
    var years: [Int]!
 
    var month = Calendar.current.component(.month, from: Date())
    var year = Calendar.current.component(.year, from: Date())

    var onDateSelected: ((_ month: Int, _ year: Int) -> Void)?
   

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.commonInit()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.commonInit()
    }
    
    func commonInit() {
        
        var years: [Int] = []
        if years.count == 0 {
        //Display from 5 years ago
        let previousDate = Calendar.current.date(byAdding: .year, value: -5, to: Date())
            var year = NSCalendar(identifier: NSCalendar.Identifier.gregorian)!.component(.year, from: previousDate!)
           
            for _ in 1...10 {
                years.append(year)
                year += 1
            }
        }
        
        self.years = years
        
        var months: [String] = []
        var month = 0
        for _ in 1...12 {
            var calendar = Calendar.current
            calendar.locale = Locale(identifier: "ja")
            let monthSymbols = calendar.monthSymbols
            months.append(monthSymbols[month])
            month += 1
        }
        
        self.months = months
        
  
        
        self.delegate = self
        self.dataSource = self
        
        //Select the current year and month
        let currentYear = Calendar(identifier: Calendar.Identifier.gregorian).component(.year, from: Date())
        let currentMonth = Calendar(identifier: Calendar.Identifier.gregorian).component(.month, from: Date())
        self.selectRow(currentMonth-1, inComponent: 1, animated: false)
        if let i = years.firstIndex(where: {$0 == currentYear}){
            self.selectRow(i, inComponent: 0, animated: false)
        }
  
    }
    
    //UIPickerDelegate&DataSource
    
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 2
    }
    
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        switch component {
        case 0:
            return "\(years[row])Year"
        case 1:
            return "\(months[row])Minutes"
        default:
            return nil
        }
    }
    
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        switch component {
        case 0:
            return years.count
        case 1:
            return months.count
        default:
            return 0
        }
    }
    
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        
        let year = years[self.selectedRow(inComponent: 0)]
        let month = self.selectedRow(inComponent: 1)+1
 
        self.month = month
        self.year = year

        if let block = onDateSelected {
            block(month, year)
        }
    }
}
  1. Set to inputView of textField with ViewDidLoad () of ViewController

 let datePickerView = MonthYearPickerView()
 datePickerView.onDateSelected = { 
   [self](month: Int, year: Int) in
   let dateText = String(format: "%d years%02d month",year,month)
   self.dateTextField.text = dateText
 }
         
 self.dateTextField.inputView = datePickerView  
 self.dateTextField.delegate = self

//I wanted to reflect the current year and month in the textField by tapping the textField, so write the following
extension ViewController: UITextFieldDelegate{
    func textFieldDidBeginEditing(_ textField: UITextField) {
        if textField == dateTextField {
            let formatter = DateFormatter()
            formatter.dateFormat = "yyyy year MM month"
            dateTextField.text = "\(formatter.string(from: Date()))"
        }
    }
}

It's done! !! ٩ ('ω') و

DatePicker is now displayed when you tap the textField like this.

スクショ

The site that I used as a reference

https://github.com/bendodson/MonthYearPickerView-Swift It's just a reference or a copy. .. .. .. Thank you: relaxed:

Recommended Posts

[Swift5] DatePicker for years only
[Swift 5] Implement UI for review function