web-dev-qa-db-fra.com

UIDatePicker sélectionner le mois et l'année

J'ai besoin d'une UIDatePicker pour sélectionner le mois et l'année uniquement. J'ai vérifié les documents de référence de la classe. On dirait que UIDatePicker est une UIView. J'imaginais que UIPickerView pouvait être une vue secondaire et je pouvais cacher le composant si je pouvais le récupérer. Mais non. Ce n'était pas possible. Dois-je créer mon propre sélecteur personnalisé alors? Des idées?

28
Dave

Oui, vous voulez probablement faire votre propre sélecteur. Vous n'êtes pas obligé de sous-classer cela ou quoi que ce soit, cependant; utilisez simplement une variable UIPickerView générique et renvoyez les valeurs appropriées à partir de vos méthodes UIPickerViewDelegate/UIPickerViewDataSource.

9
Noah Witherspoon

Voici une solution pour obtenir le même effet. Pour utiliser cet extrait de code, vous devez remplacer UIPickerView par CDatePickerViewEx dans le fichier nib dans "Classe personnalisée" de "Inspecteur d'identité".

Fichier .h

#import <UIKit/UIKit.h>

@interface CDatePickerViewEx : UIPickerView <UIPickerViewDelegate, UIPickerViewDataSource> 

@property (nonatomic, strong, readonly) NSDate *date;
-(void)selectToday;

@end

fichier .m

#import "CDatePickerViewEx.h"

// Identifiers of components
#define MONTH ( 0 )
#define YEAR ( 1 )    

// Identifies for component views
#define LABEL_TAG 43


@interface CDatePickerViewEx()

@property (nonatomic, strong) NSIndexPath *todayIndexPath;
@property (nonatomic, strong) NSArray *months;
@property (nonatomic, strong) NSArray *years;

-(NSArray *)nameOfYears;
-(NSArray *)nameOfMonths;
-(CGFloat)componentWidth;

-(UILabel *)labelForComponent:(NSInteger)component selected:(BOOL)selected;
-(NSString *)titleForRow:(NSInteger)row forComponent:(NSInteger)component;
-(NSIndexPath *)todayPath;
-(NSInteger)bigRowMonthCount;
-(NSInteger)bigRowYearCount;
-(NSString *)currentMonthName;
-(NSString *)currentYearName;

@end

@implementation CDatePickerViewEx

const NSInteger bigRowCount = 1000; 
const NSInteger minYear = 2008;
const NSInteger maxYear = 2030;
const CGFloat rowHeight = 44.f;
const NSInteger numberOfComponents = 2;

@synthesize todayIndexPath;
@synthesize months;
@synthesize years = _years;

-(void)awakeFromNib
{
    [super awakeFromNib];

    self.months = [self nameOfMonths];
    self.years = [self nameOfYears];
    self.todayIndexPath = [self todayPath];

    self.delegate = self;
    self.dataSource = self;

    [self selectToday];
}

-(NSDate *)date
{
    NSInteger monthCount = [self.months count];
    NSString *month = [self.months objectAtIndex:([self selectedRowInComponent:MONTH] % monthCount)];

    NSInteger yearCount = [self.years count];
    NSString *year = [self.years objectAtIndex:([self selectedRowInComponent:YEAR] % yearCount)];

    NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setDateFormat:@"MMMM:yyyy"];
    NSDate *date = [formatter dateFromString:[NSString stringWithFormat:@"%@:%@", month, year]];
    return date;
}

#pragma mark - UIPickerViewDelegate
-(CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component
{
    return [self componentWidth];
}

-(UIView *)pickerView: (UIPickerView *)pickerView
            viewForRow: (NSInteger)row
          forComponent: (NSInteger)component
           reusingView: (UIView *)view
{   
    BOOL selected = NO;    
    if(component == MONTH)
    {
        NSInteger monthCount = [self.months count];
        NSString *monthName = [self.months objectAtIndex:(row % monthCount)]; 
        NSString *currentMonthName = [self currentMonthName];
        if([monthName isEqualToString:currentMonthName] == YES)
        {
            selected = YES;
        }
    }
    else
    {
        NSInteger yearCount = [self.years count];
        NSString *yearName = [self.years objectAtIndex:(row % yearCount)];
        NSString *currenrYearName  = [self currentYearName];
        if([yearName isEqualToString:currenrYearName] == YES)
        {
            selected = YES;
        }
    }

    UILabel *returnView = nil;
    if(view.tag == LABEL_TAG)
    {
        returnView = (UILabel *)view;
    }
    else 
    {
        returnView = [self labelForComponent: component selected: selected];
    }

    returnView.textColor = selected ? [UIColor blueColor] : [UIColor blackColor];
    returnView.text = [self titleForRow:row forComponent:component];
    return returnView;
}

-(CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component
{
    return rowHeight;
}

#pragma mark - UIPickerViewDataSource
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
    return numberOfComponents;
}

-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    if(component == MONTH)
    {
        return [self bigRowMonthCount];
    }
    return [self bigRowYearCount];
}

#pragma mark - Util
-(NSInteger)bigRowMonthCount
{
    return [self.months count]  * bigRowCount;
}

-(NSInteger)bigRowYearCount
{
    return [self.years count]  * bigRowCount;
}

-(CGFloat)componentWidth
{
    return self.bounds.size.width / numberOfComponents;
}

-(NSString *)titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    if(component == MONTH)
    {
        NSInteger monthCount = [self.months count];
        return [self.months objectAtIndex:(row % monthCount)]; 
    }
    NSInteger yearCount = [self.years count];
    return [self.years objectAtIndex:(row % yearCount)];
}

-(UILabel *)labelForComponent:(NSInteger)component selected:(BOOL)selected
{
    CGRect frame = CGRectMake(0.f, 0.f, [self componentWidth],rowHeight);

    UILabel *label = [[UILabel alloc] initWithFrame:frame];
    label.textAlignment = UITextAlignmentCenter;
    label.backgroundColor = [UIColor clearColor];
    label.textColor = selected ? [UIColor blueColor] : [UIColor blackColor];
    label.font = [UIFont boldSystemFontOfSize:18.f];
    label.userInteractionEnabled = NO;

    label.tag = LABEL_TAG;

    return label;
}

-(NSArray *)nameOfMonths
{    
    NSDateFormatter *dateFormatter = [NSDateFormatter new];
    return [dateFormatter standaloneMonthSymbols];
}

-(NSArray *)nameOfYears
{
    NSMutableArray *years = [NSMutableArray array];

    for(NSInteger year = minYear; year <= maxYear; year++) 
    {
        NSString *yearStr = [NSString stringWithFormat:@"%i", year];
        [years addObject:yearStr];
    }
    return years;
}

-(void)selectToday
{
    [self selectRow: self.todayIndexPath.row
        inComponent: MONTH
           animated: NO];

    [self selectRow: self.todayIndexPath.section
        inComponent: YEAR
           animated: NO];
}

-(NSIndexPath *)todayPath // row - month ; section - year
{
    CGFloat row = 0.f;
    CGFloat section = 0.f;

    NSString *month = [self currentMonthName];
    NSString *year  = [self currentYearName];

    //set table on the middle
    for(NSString *cellMonth in self.months) 
    {
        if([cellMonth isEqualToString:month]) 
        {
            row = [self.months indexOfObject:cellMonth];
            row = row + [self bigRowMonthCount] / 2;
            break;
        }
    }

    for(NSString *cellYear in self.years) 
    {
        if([cellYear isEqualToString:year]) 
        {
            section = [self.years indexOfObject:cellYear];
            section = section + [self bigRowYearCount] / 2;
            break;
        }
    }

    return [NSIndexPath indexPathForRow:row inSection:section];
}

-(NSString *)currentMonthName
{
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"MMMM"];
    return [formatter stringFromDate:[NSDate date]];
}

-(NSString *)currentYearName
{
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyy"];
    return [formatter stringFromDate:[NSDate date]];
}

@end
16
Igor

Non, cela ne peut pas être fait avec la valeur de stock UIDatePicker.

UIDatePickerModeDate

Le sélecteur de date affiche les mois, les jours du mois et des années. L'ordre exact de ceux-ci Les éléments dépendent des paramètres régionaux . Un exemple de ce mode est [novembre | 15 | 2007].

Source: Référence de classe UIDatePicker

Je recommande de personnaliser un UIPickerView afin d’utiliser deux composants et de renseigner ses lignes avec les symboles de mois et d’année extraits de NSDateFormatter .

4
Justin

J'ai récrit la réponse d'Igor dans Swift:

class CLIVEDatePickerView: UIPickerView  {

    enum Component: Int {
        case Month = 0
        case Year = 1
    }

    let LABEL_TAG = 43
    let bigRowCount = 1000
    let numberOfComponentsRequired = 2

    let months = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"]
    var years: [String] {
        get {
            var years: [String] = [String]()

            for i in minYear...maxYear {
                years.append("\(i)")
            }

            return years;
        }
    }

    var bigRowMonthsCount: Int {
        get {
            return bigRowCount * months.count
        }
    }

    var bigRowYearsCount: Int {
        get {
            return bigRowCount * years.count
        }
    }

    var monthSelectedTextColor: UIColor?
    var monthTextColor: UIColor?
    var yearSelectedTextColor: UIColor?
    var yearTextColor: UIColor?
    var monthSelectedFont: UIFont?
    var monthFont: UIFont?
    var yearSelectedFont: UIFont?
    var yearFont: UIFont?

    let rowHeight: NSInteger = 44

    /**
     Will be returned in user's current TimeZone settings
    **/
    var date: NSDate {
        get {
            let month = self.months[selectedRowInComponent(Component.Month.rawValue) % months.count]
            let year = self.years[selectedRowInComponent(Component.Year.rawValue) % years.count]
            let formatter = NSDateFormatter()
            formatter.dateFormat = "MM yyyy"
            return formatter.dateFromString("\(month) \(year)")!
        }
    }

    var minYear: Int!
    var maxYear: Int!

    override init(frame: CGRect) {
        super.init(frame: frame)
        loadDefaultParameters()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        loadDefaultParameters()
    }
    override func awakeFromNib() {
        super.awakeFromNib()
        loadDefaultParameters()
    }

    func loadDefaultParameters() {
        minYear = NSCalendar.currentCalendar().components(NSCalendarUnit.Year, fromDate: NSDate()).year
        maxYear = minYear! + 10

        self.delegate = self
        self.dataSource = self

        monthSelectedTextColor = UIColor.blueColor()
        monthTextColor = UIColor.blackColor()

        yearSelectedTextColor = UIColor.blueColor()
        yearTextColor = UIColor.blackColor()

        monthSelectedFont = UIFont.boldSystemFontOfSize(17)
        monthFont = UIFont.boldSystemFontOfSize(17)

        yearSelectedFont = UIFont.boldSystemFontOfSize(17)
        yearFont = UIFont.boldSystemFontOfSize(17)
    }


    func setup(minYear: NSInteger, andMaxYear maxYear: NSInteger) {
        self.minYear = minYear

        if maxYear > minYear {
            self.maxYear = maxYear
        } else {
            self.maxYear = minYear + 10
        }
    }

    func selectToday() {
        selectRow(todayIndexPath.row, inComponent: Component.Month.rawValue, animated: false)
        selectRow(todayIndexPath.section, inComponent: Component.Year.rawValue, animated: false)
    }


    var todayIndexPath: NSIndexPath {
        get {
            var row = 0.0
            var section = 0.0

            for cellMonth in months {
                if cellMonth == currentMonthName {
                    row = Double(months.indexOf(cellMonth)!)
                    row = row + Double(bigRowMonthsCount / 2)
                    break
                }
            }

            for cellYear in years {
                if cellYear == currentYearName {
                    section = Double(years.indexOf(cellYear)!)
                    section = section + Double(bigRowYearsCount / 2)
                    break
                }
            }

            return NSIndexPath(forRow: Int(row), inSection: Int(section))
        }
    }

    var currentMonthName: String {
        get {
            let formatter = NSDateFormatter()
            let locale = NSLocale(localeIdentifier: "en_US")
            formatter.locale = locale
            formatter.dateFormat = "MM"
            return formatter.stringFromDate(NSDate())
        }
    }

    var currentYearName: String {
        get {
            let formatter = NSDateFormatter()
            formatter.dateFormat = "yyyy"
            return formatter.stringFromDate(NSDate())
        }
    }


    func selectedColorForComponent(component: NSInteger) -> UIColor {
        if component == Component.Month.rawValue {
            return monthSelectedTextColor!
        }
        return yearSelectedTextColor!
    }

    func colorForComponent(component: NSInteger) -> UIColor {
        if component == Component.Month.rawValue {
            return monthTextColor!
        }
        return yearTextColor!
    }


    func selectedFontForComponent(component: NSInteger) -> UIFont {
        if component == Component.Month.rawValue {
            return monthSelectedFont!
        }
        return yearSelectedFont!
    }

    func fontForComponent(component: NSInteger) -> UIFont {
        if component == Component.Month.rawValue {
            return monthFont!
        }
        return yearFont!
    }



    func titleForRow(row: Int, forComponent component: Int) -> String? {
        if component == Component.Month.rawValue {
            return self.months[row % self.months.count]
        }
        return self.years[row % self.years.count]
    }


    func labelForComponent(component: NSInteger) -> UILabel {
        let frame = CGRect(x: 0.0, y: 0.0, width: bounds.size.width, height: CGFloat(rowHeight))
        let label = UILabel(frame: frame)
        label.textAlignment = NSTextAlignment.Center
        label.backgroundColor = UIColor.clearColor()
        label.userInteractionEnabled = false
        label.tag = LABEL_TAG
        return label
    }
}

extension CLIVEDatePickerView: UIPickerViewDelegate, UIPickerViewDataSource {

    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
        return numberOfComponentsRequired
    }

    func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        if(component == Component.Month.rawValue) {
            return bigRowMonthsCount
        } else {
            return bigRowYearsCount
        }
    }



    func pickerView(pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat {
        return self.bounds.size.width / CGFloat(numberOfComponentsRequired)
    }

    func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView?) -> UIView {
        var selected = false

        if component == Component.Month.rawValue {
            let monthName = self.months[(row % self.months.count)]
            if monthName == currentMonthName {
                selected = true
            }
        } else {
            let yearName = self.years[(row % self.years.count)]
            if yearName == currentYearName {
                selected = true
            }
        }

        var returnView: UILabel
        if view?.tag == LABEL_TAG {
            returnView = view as! UILabel
        } else {
            returnView = labelForComponent(component)
        }

        returnView.font = selected ? selectedFontForComponent(component) : fontForComponent(component)
        returnView.textColor = selected ? selectedColorForComponent(component) : colorForComponent(component)

        returnView.text = titleForRow(row, forComponent: component)

        return returnView
    }


    func pickerView(pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
        return CGFloat(rowHeight)
    }

}
4
RossP

J'ai un contournement paresseux - j'ai créé un png noir 10x10 ..__, que j'ai ensuite utilisé comme masque avec une image scaletofill dimensionnée pour couvrir parfaitement la colonne des dates. Je mets l'alpha à 0,75 pour montrer à peine cette colonne. Il est clair pour l'utilisateur et semble décent.

2
Mischa

J'utilise une simple UIPickerView avec 2 composants (mois et années).

Et en appelant la UIPickerViewDelegate avec chaque sélection de ligne:

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
    //Today year and month
    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat:@"yyyy"];
    int year = [[dateFormat stringFromDate:[NSDate date]] intValue];
    [dateFormat setDateFormat:@"MM"];
    int month = [[dateFormat stringFromDate:[NSDate date]] intValue] - 1;

    //picker year and month
    int selectedYear = [[self.yearsArray objectAtIndex:[pickerView selectedRowInComponent:1]] intValue];
    int selectedMonth = [pickerView selectedRowInComponent:0];

    // if month in the past, change the month
    if (year == selectedYear && selectedMonth < month)
    {
        [pickerView selectRow:month inComponent:0 animated:YES];
    }
}
1
Gabriel.Massana

Je viens de réinitialiser le jour au premier du mois lorsque l'événement de changement de valeur se produit comme ci-dessous. Ainsi, lorsque l'utilisateur sélectionne un jour, il revient au 1er. J'utilise ensuite pour sélectionner la date de début (mois et année).

-(void) resetDay {

 NSDate *currentDate  = [startDatePicker date];
 NSCalendar *gregorian = [[NSCalendar alloc]  initWithCalendarIdentifier:NSGregorianCalendar];
 NSDateComponents *componentsYear = [gregorian components:(NSYearCalendarUnit| NSMonthCalendarUnit) fromDate:currentDate];
 NSInteger yearNum = [ componentsYear year];
 NSInteger monthNum = [componentsYear month];
 NSLog(@"Month %d, Year %d", monthNum, yearNum);

 NSDateComponents *componentStartDate = [[NSDateComponents alloc] init];
 [componentStartDate setDay:1];
 [componentStartDate setMonth:monthNum];
 [componentStartDate setYear:yearNum];
 NSDate *startDate = [gregorian dateFromComponents:componentStartDate];

 [startDatePicker setDate:startDate animated:YES];
 [componentStartDate release];
 [gregorian release];
}

Pour sélectionner la date de fin (mois et année), il est un peu plus long, car je voulais régler le jour au 31 ou au 30 du mois sélectionné.

-(NSInteger) findDaysInYear {
    NSDate *currentDate = [NSDate date];
    NSCalendar *gregorian = [[NSCalendar alloc]  initWithCalendarIdentifier:NSGregorianCalendar];


    NSDateComponents *componentsYear = [gregorian components:(NSYearCalendarUnit)   fromDate:currentDate];
    NSInteger yearNum = [ componentsYear year];

    NSDateComponents *componentStartDate = [[NSDateComponents alloc] init];
    [componentStartDate setDay:1];
    [componentStartDate setMonth:1];
    [componentStartDate setYear:yearNum];
    NSDate *startDate = [gregorian dateFromComponents:componentStartDate];
    NSLog(@"Start date set to %@", startDate);

    NSDateComponents *componentEndDate = [[NSDateComponents alloc] init];
    [componentEndDate setDay:31];
    [componentEndDate setMonth:12];
    [componentEndDate setYear:yearNum];

    NSDate *endDate = [gregorian dateFromComponents:componentEndDate];
    NSLog(@"End date set to %@", endDate);

    NSUInteger unitFlags = NSDayCalendarUnit ;
    NSDateComponents *componentsDay = [gregorian components:unitFlags   fromDate:startDate    toDate:endDate options:0];
    NSInteger days = [componentsDay day] +1;
    NSLog(@"Number of days in the year:%d, is %d", yearNum,days);
    [componentEndDate release];
    [componentStartDate release];
    [gregorian release];
    if (days != 365 && days != 366) {
        return 366;
    }
    return days;
}
-(NSInteger) findDaysInMonth:(NSInteger) monthNum {

    NSInteger days = 30;


    switch (monthNum) {
        case 1:
            days = 31;
            break;
        case 2:
            if([self findDaysInYear] == 366)        days = 29;
            else days = 28;
            break;
        case 3:
            days = 31;
            break;
        case 4:
            days = 30;
            break;
        case 5:
            days = 31;
            break;
        case 6:
            days = 30;
            break;
        case 7:
            days = 31;
            break;
        case 8:
            days = 31;
            break;
        case 9:
            days = 30;
            break;
        case 10:
            days = 31;
            break;
        case 11:
            days = 30;
            break;
        case 12:
            days = 31;
            break;
        default:
            break;
    }
    return days;

}

-(void) resetDay {

    NSDate *currentDate  = [endDatePicker date];
    NSCalendar *gregorian = [[NSCalendar alloc]  initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents *componentsYear = [gregorian components:(NSYearCalendarUnit| NSMonthCalendarUnit)  fromDate:currentDate];
    NSInteger yearNum = [ componentsYear year];
    NSInteger monthNum = [componentsYear month];

    NSDateComponents *componentStartDate = [[NSDateComponents alloc] init];
    [componentStartDate setDay:[self findDaysInMonth:monthNum]];
    [componentStartDate setMonth:monthNum];
    [componentStartDate setYear:yearNum];
    NSDate *startDate = [gregorian dateFromComponents:componentStartDate];

    [endDatePicker setDate:startDate animated:YES];
    [componentStartDate release];
    [gregorian release];
}
1
Gamma-Point

Réécrit réponse de RossP dans Swift 4:

import Foundation

@objc class ShortDatePickerView: UIPickerView  {

    enum Component: Int {
        case Month = 0
        case Year = 1
    }

    let LABEL_TAG = 43
    let bigRowCount = 1000
    let numberOfComponentsRequired = 2

    let months = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"]
    var years: [String] {
        get {
            var years: [String] = [String]()

            for i in minYear...maxYear {
                years.append("\(i)")
            }

            return years;
        }
    }

    var bigRowMonthsCount: Int {
        get {
            return bigRowCount * months.count
        }
    }

    var bigRowYearsCount: Int {
        get {
            return bigRowCount * years.count
        }
    }

    var monthSelectedTextColor: UIColor?
    var monthTextColor: UIColor?
    var yearSelectedTextColor: UIColor?
    var yearTextColor: UIColor?
    var monthSelectedFont: UIFont?
    var monthFont: UIFont?
    var yearSelectedFont: UIFont?
    var yearFont: UIFont?

    let rowHeight: NSInteger = 44

    /**
     Will be returned in user's current TimeZone settings
    **/
    var date: Date {
        get {
            let month = self.months[selectedRow(inComponent: Component.Month.rawValue) % months.count]
            let year = self.years[selectedRow(inComponent: Component.Year.rawValue) % years.count]
            let formatter = DateFormatter()
            formatter.dateFormat = "MM yyyy"
            return formatter.date(from: "\(month) \(year)")!
        }
    }

    var minYear: Int!
    var maxYear: Int!

    override init(frame: CGRect) {
        super.init(frame: frame)
        loadDefaultParameters()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        loadDefaultParameters()
    }

    override func awakeFromNib() {
        super.awakeFromNib()
        loadDefaultParameters()
    }

    func loadDefaultParameters() {
        minYear = Calendar.current.dateComponents([.year], from: Date()).year
        maxYear = minYear! + 10

        self.delegate = self
        self.dataSource = self

        monthSelectedTextColor = .blue
        monthTextColor = .black

        yearSelectedTextColor = .blue
        yearTextColor = .black

        monthSelectedFont = .boldSystemFont(ofSize: 17)
        monthFont = .boldSystemFont(ofSize: 17)

        yearSelectedFont = .boldSystemFont(ofSize: 17)
        yearFont = .boldSystemFont(ofSize: 17)
    }


    func setup(minYear: NSInteger, andMaxYear maxYear: NSInteger) {
        self.minYear = minYear

        if maxYear > minYear {
            self.maxYear = maxYear
        } else {
            self.maxYear = minYear + 10
        }
    }

    func selectToday() {
        selectRow(todayIndexPath.row, inComponent: Component.Month.rawValue, animated: false)
        selectRow(todayIndexPath.section, inComponent: Component.Year.rawValue, animated: false)
    }


    var todayIndexPath: NSIndexPath {
        get {
            var row = 0.0
            var section = 0.0

            for cellMonth in months {
                if cellMonth == currentMonthName {
                    row = Double(months.index(of: cellMonth)!)
                    row = row + Double(bigRowMonthsCount / 2)
                    break
                }
            }

            for cellYear in years {
                if cellYear == currentYearName {
                    section = Double(years.index(of: cellYear)!)
                    section = section + Double(bigRowYearsCount / 2)
                    break
                }
            }

            return NSIndexPath(row: Int(row), section: Int(section))
        }
    }

    var currentMonthName: String {
        get {
            let formatter = DateFormatter()
            let locale = Locale.init(identifier: "en_US")
            formatter.locale = locale
            formatter.dateFormat = "MM"
            return formatter.string(from: Date())
        }
    }

    var currentYearName: String {
        get {
            let formatter = DateFormatter()
            formatter.dateFormat = "yyyy"
            return formatter.string(from: Date())
        }
    }


    func selectedColorForComponent(component: NSInteger) -> UIColor {
        if component == Component.Month.rawValue {
            return monthSelectedTextColor!
        }
        return yearSelectedTextColor!
    }

    func colorForComponent(component: NSInteger) -> UIColor {
        if component == Component.Month.rawValue {
            return monthTextColor!
        }
        return yearTextColor!
    }


    func selectedFontForComponent(component: NSInteger) -> UIFont {
        if component == Component.Month.rawValue {
            return monthSelectedFont!
        }
        return yearSelectedFont!
    }

    func fontForComponent(component: NSInteger) -> UIFont {
        if component == Component.Month.rawValue {
            return monthFont!
        }
        return yearFont!
    }


    func titleForRow(row: Int, forComponent component: Int) -> String? {
        if component == Component.Month.rawValue {
            return self.months[row % self.months.count]
        }
        return self.years[row % self.years.count]
    }


    func labelForComponent(component: NSInteger) -> UILabel {
        let frame = CGRect(x: 0.0, y: 0.0, width: bounds.size.width, height: CGFloat(rowHeight))
        let label = UILabel(frame: frame)
        label.textAlignment = .center
        label.backgroundColor = .clear
        label.isUserInteractionEnabled = false
        label.tag = LABEL_TAG
        return label
    }
}

extension ShortDatePickerView: UIPickerViewDelegate, UIPickerViewDataSource {

    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
        return numberOfComponentsRequired
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        if (component == Component.Month.rawValue) {
            return bigRowMonthsCount
        } else {
            return bigRowYearsCount
        }
    }

    func pickerView(_ pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat {
        return self.bounds.size.width / CGFloat(numberOfComponentsRequired)
    }

    func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
        var selected = false

        if component == Component.Month.rawValue {
            let monthName = self.months[(row % self.months.count)]
            if monthName == currentMonthName {
                selected = true
            }
        } else {
            let yearName = self.years[(row % self.years.count)]
            if yearName == currentYearName {
                selected = true
            }
        }

        var returnView: UILabel
        if view?.tag == LABEL_TAG {
            returnView = view as! UILabel
        } else {
            returnView = labelForComponent(component: component)
        }

        returnView.font = selected ? selectedFontForComponent(component: component) : fontForComponent(component: component)
        returnView.textColor = selected ? selectedColorForComponent(component: component) : colorForComponent(component: component)

        returnView.text = titleForRow(row: row, forComponent: component)

        return returnView
    }

    func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
        return CGFloat(rowHeight)
    }

    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 2
    }
}
0
George

Vous pouvez utiliser UICustomDatePicker pour afficher uniquement les options de mois et d'année. 

https://github.com/Anandsan/UICustomDatePicker

@interface ViewController ()

@property (nonatomic, weak) IBOutlet UICustomDatePicker *customDatePicker;

@end

-(void) viewDidLoad {

 [super viewDidLoad];

 self.customDatePicker.option = NSCustomDatePickerOptionLongMonth | NSCustomDatePickerOptionYear;

 self.customDatePicker.order = NSCustomDatePickerOrderMonthDayAndYear;

}

 -(IBAction)didCustomDatePickerValueChanged:(id)sender {

    NSLog(@"%@",[(UICustomDatePicker *)sender currentDate]);

}

Voir l'écran

0
anand sankaran

Vous pouvez utiliser la bibliothèque open source nommée 

AKMonthYearPickerView

import AKMonthYearPickerView

AKMonthYearPickerView.sharedInstance.show(vc: viewController, doneHandler: doneHandler, completetionalHandler: completetionalHandler)

https://github.com/ALi-cs/AKMonthYearPickerView

pour l'installer à l'aide de pods, 

pod 'AKMonthYearPickerView' 

pour personnaliser la limite et la couleur des barres des années précédentes

AKMonthYearPickerView.sharedInstance.barTintColor =   UIColor.blue

AKMonthYearPickerView.sharedInstance.previousYear = 4

 enter image description here

0
Ali