UIDatePicker to show year only

前端 未结 6 509
时光取名叫无心
时光取名叫无心 2020-12-07 00:51

Is there a way to have a UIDatePicker show year only?

相关标签:
6条回答
  • 2020-12-07 01:32

    Just updating the existing answer in this post with Swift 3:

    var yearsTillNow : [String] {
        var years = [String]()
        for i in (1970..<2018).reversed() {
            years.append("\(i)")
        }
        return years
    }
    

    Just use this for your UIPickerView datasource.

    0 讨论(0)
  • 2020-12-07 01:34

    It is not possible to set only Year and Month. Only these modes are available as of iOS 13.5.1

    • time: A mode that displays the date in hours, minutes, and (optionally) an AM/PM designation. The exact items shown and their order depend upon the locale set. An example of this mode is [ 6 | 53 | PM ].

    • date: A mode that displays the date in months, days of the month, and years. The exact order of these items depends on the locale setting. An example of this mode is [ November | 15 | 2007 ].

    • dateAndTime: A mode that displays the date as unified day of the week, month, and day of the month values, plus hours, minutes, and (optionally) an AM/PM designation. The exact order and format of these items depends on the locale set. An example of this mode is [ Wed Nov 15 | 6 | 53 | PM ].

    • countDownTimer: A mode that displays hour and minute values, for example [ 1 | 53 ]. The application must set a timer to fire at the proper interval and set the date picker as the seconds tick down. UIDatePicker.Mode - developer.apple.com


    You may build it using a custom UIPickerView.

    class DatePickerViewController: UIViewController {
        var dates =  [Date]()
        override func viewDidLoad() {
            super.viewDidLoad()
            self.view.backgroundColor = .white
            
            
            var date = Date().addYear(n: -10)
            let endDate = Date().addYear(n: 10)
            
            repeat {
                date = date.addMonth(n: 1)
                dates.append(date)
            } while date < endDate
            
            
            let picker = UIPickerView()
            picker.dataSource = self
            picker.delegate = self
            picker.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview(picker)
            
            picker.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
            picker.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
            picker.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
            picker.heightAnchor.constraint(equalToConstant: 500).isActive = true
        }
    }
    
    
    extension  DatePickerViewController: UIPickerViewDataSource {
        func numberOfComponents(in pickerView: UIPickerView) -> Int {
            return 1
        }
        
        func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
            return self.dates.count
        }
        
        func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
            let date = self.dates[row]
            return date.stringDate()
        }
        
        func view(forRow row: Int, forComponent component: Int) -> UIView? {
            let label =  UILabel()
            return label
        }
    }
    
    extension  DatePickerViewController: UIPickerViewDelegate {
        func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
            let date = self.dates[row]
            // Date that the user select. 
            print( date, date.stringDate())
        }
    }
    
    
    extension Date {
        public  func addYear(n: Int) -> Date {
            let calendar = Calendar.current
            return calendar.date(byAdding: .year, value: n, to: self)!
        }
        
        public  func addMonth(n: Int) -> Date {
            let calendar = Calendar.current
            return calendar.date(byAdding: .month, value: n, to: self)!
        }
        
        public  func stringDate() -> String {
            let calendar  = Calendar.current
            let dateFormatter = DateFormatter()
            
            dateFormatter.timeZone = calendar.timeZone
            dateFormatter.locale = calendar.locale
            // Use YYYY to show year only. 
            // Use MMMM to show month only. 
            dateFormatter.setLocalizedDateFormatFromTemplate("MMMM YYYY")
            
            let dateString = dateFormatter.string(from: self)
            return dateString
        }
    }
    

    Just change the following two lines- add/subtract as many years you wish to show.

    var date = Date().addYear(n: -10) 
    let endDate = Date().addYear(n: 10)
    

    0 讨论(0)
  • 2020-12-07 01:35

    You can't do this with UIDatePicker, but you can with UIPicker.

    You need to create an array for the years, and add them to the UIPicker using the UIPicker delegates

    Here's a tutorial.

    0 讨论(0)
  • 2020-12-07 01:41

    I have a little code that I was about to delete, but the snippet is better off if it is online somewhere. It's not amazing, but it is searchable!

    Objective-C code to create an array of all years since 1960. Perfect for input into a UIPicker

    //Get Current Year into i2
    NSDateFormatter* formatter = [[[NSDateFormatter alloc] init]autorelease];
    [formatter setDateFormat:@"yyyy"];
    int i2  = [[formatter stringFromDate:[NSDate date]] intValue];
    
    
    //Create Years Array from 1960 to This year
    years = [[NSMutableArray alloc] init];
    for (int i=1960; i<=i2; i++) {
        [years addObject:[NSString stringWithFormat:@"%d",i]];
    }
    

    The UIPickerView data source and delegate methods:

    - (NSInteger)numberOfComponentsInPickerView: (UIPickerView*)thePickerView {
        return 1;
    }
    
    - (NSInteger)pickerView:(UIPickerView *)thePickerView numberOfRowsInComponent:(NSInteger)component
    {
        return [years count];
    }
    - (NSString *)pickerView:(UIPickerView *)thePickerView
    titleForRow:(NSInteger)row forComponent:(NSInteger)component
    {
        return [years objectAtIndex:row];
    }
    

    Don't forget the declaration in the interface

    //Data
    NSMutableArray *years;
    

    The out put of it is

    enter image description here

    Referenced from here

    0 讨论(0)
  • 2020-12-07 01:55

    I changed Sharukh Mastan's code slightly to always show the current year on top.

    var formattedDate: String? = ""
    
    let format = DateFormatter()
    format.dateFormat = "yyyy"
    formattedDate = format.string(from: date)
    
    var yearsTillNow: [String] {
        var years = [String]()
        for i in (Int(formattedDate!)!-70..<Int(formattedDate!)!+1).reversed() {
            years.append("\(i)")
        }
        return years
    }
    
    print(yearsTillNow)
    

    This prints an array of years going back for 70 years which you can use as UIPickerView datasource

    0 讨论(0)
  • 2020-12-07 01:58

    I cannot comment, but I was playing around with the answer by Wolvorin and I decided to do a way where the most recent year would be at the top of the Picker. Currently, his code goes oldest to most recent years.

    All I changes was in my NSMutableArray setup in the viewDidLoad instead of his:

    //Create Years Array from 1960 to This year
    years = [[NSMutableArray alloc] init];
    for (int i=1960; i<=i2; i++) {
        [years addObject:[NSString stringWithFormat:@"%d",i]];
    }
    

    I used:

    years = [[NSMutableArray alloc] init];
    for (int i1=i2; i1<=i2 & i1>=1920; i1--) {
        [years addObject:[NSString stringWithFormat:@"%d",i1]];
    }
    

    Which does the for in reversed order going from the most recent date, then subtracting one year (and adding it to the Array) until it gets to 1920.

    My formula:

    int i1=i2; i1<=i2 & i1>=1920; i1--
    
    0 讨论(0)
提交回复
热议问题