ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

IOS实现日期选择器

2021-06-28 14:03:51  阅读:209  来源: 互联网

标签:NSInteger pickerView return UIPickerView component self IOS 日期 选择器


选择器,我想大家都不陌生,当需要用户去选择某些范围值内的一个固定值时,我们会采用选择器的方式。选择器可以直观的提示用户选择的值范围、统一信息的填写格式,同时也方便用户快速的进行选择,比如对于性别,正常情况下就只有男女两种情况,那这时候用一个选择器给用户进行选择的话,可以避免错误数据的输入,也更方便用户去填写。再比如需要获取用户的生日信息时,采用选择器的方式可以统一生日的格式,如果让用户自行输入的话,可能会出现各种各样的生日信息格式,不利于数据的存储,但是采用选择器的方式的话,用户可找到对应的日期进行选择即可。

一、为选择器创建Model

Model的形式主要是在选择器每一列的各个属性,下面以时间选择器为例子

@interface DateModel : NSObject

@property (nonatomic, retain) NSString *year;
@property (nonatomic, retain) NSString *month;
@property (nonatomic, retain) NSString *day;
@property (nonatomic, retain) NSString *hour;
@property (nonatomic, retain) NSString *minute;

- (id)initWithDate:(NSDate *)date
{
    self = [super init];
    if (self) {
        NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
        [formatter setDateFormat:@"yyyyMMddHHmm"];
        NSString *dateString = [formatter stringFromDate:date];

        self.year     = [dateString substringWithRange:NSMakeRange(0, 4)];
        self.month    = [dateString substringWithRange:NSMakeRange(4, 2)];
        self.day      = [dateString substringWithRange:NSMakeRange(6, 2)];
        self.hour     = [dateString substringWithRange:NSMakeRange(8, 2)];
        self.minute   = [dateString substringWithRange:NSMakeRange(10, 2)];
    }
    return self;
}

@end

@end

二、实现UIPickerView的代理方法

(1)UIPickerViewDataSource对应的代理方法有(其代理方法必须要实现):

返回显示的列数

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView;

返回每一列中需要显示的行数

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component;

(2)UIPickerViewDelegate对应的代理方法(其代理方法根据需求进行选择性实现):

返回每一列的宽度

- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component;

返回每一列的高度

- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component ;

返回UIPickerView控件中指定列的列表项的要显示的内容

- (nullable NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component ;

返回UIView,作为该UIPickerView控件中指定列的指定行的显示视图

- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(nullable UIView *)view ;

选择指定列中的指定行

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component ;

三、实现自定义的PickerView

下面以我自己封装的自定义PickerView为例子

@interface YTDatePick(){
    /**
     *  记录位置
     *
     */
    NSInteger yearIndex;
    NSInteger monthIndex;
    NSInteger dayIndex;
    NSInteger hourIndex;
    NSInteger minuteIndex;
    NSArray *_indexArray;
}

@property (nonatomic, assign) BOOL isMySelect;

@end

@interface NSNumber (StringValue)

//@property (nonatomic, copy)NSString *string;

@end


@implementation NSNumber (StringValue)

- (NSString *)string{
    if (self.integerValue >= 10) {
        return [NSString stringWithFormat:@"%@", self];
    }else{
        return [NSString stringWithFormat:@"0%@", self];
    }
}

@end

@interface MyPickViews: UIPickerView<UIPickerViewDelegate,UIPickerViewDataSource>

- (void)showPickViewWithFrame:(CGRect )frame
                     delegate:(id)delegate
                      supView:(UIView *)supView
      numberOfRowsInComponent:(NSInteger(^)(NSInteger component))numberOfRowsInComponent
                  titleForRow:(UIView *(^)(NSInteger row, NSInteger component))titleForRow
                 didSelectRow:(void(^)(NSInteger row, NSInteger component))didSelectRow;

@property (nonatomic, copy)NSInteger(^numberOfRowsInComponent)(NSInteger  component);
@property (nonatomic, copy)UIView *(^titleForRow)(NSInteger row, NSInteger component);
@property (nonatomic, copy)void(^didSelectRow)(NSInteger row, NSInteger component);


@end



@implementation MyPickViews


- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
    return 1;
}
- (void)showPickViewWithFrame:(CGRect)frame delegate:(id)delegate supView:(UIView *)supView numberOfRowsInComponent:(NSInteger (^)(NSInteger ))numberOfRowsInComponent titleForRow:(UIView *(^)(NSInteger, NSInteger))titleForRow didSelectRow:(void (^)(NSInteger, NSInteger))didSelectRow{
    self.delegate = self;
    self.dataSource = self;
    self.frame = frame;
    
    
    if ([supView.subviews containsObject:self]) {
        
    }else {
        [supView addSubview:self];
    }
    self.numberOfRowsInComponent = numberOfRowsInComponent;
    self.titleForRow = titleForRow;
    self.didSelectRow = didSelectRow;
    
    NSLog(@"%@", self.titleForRow);
}
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component{
    return 50;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
    if (self.numberOfRowsInComponent) {
        return self.numberOfRowsInComponent(component);
    }else{
        return 0;
    }
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
    self.didSelectRow(row , component);
}
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view{
    [pickerView.subviews[1] setBackgroundColor:kColorNAVI_BULE];
    [pickerView.subviews[2] setBackgroundColor:kColorNAVI_BULE];
    
    return self.titleForRow(row, component);
}
@end

static void(^dayClickSureBlock)(id, id, id);

@interface YTDatePick ()

@property (nonatomic, strong)MyPickViews *firstTable, *secondTable, *thirdTable;
@property (nonatomic, assign)NSInteger fistSelect, secSelect,thirdSelect;
@property (nonatomic, strong)NSArray *dataArr;
@end

@implementation YTDatePick

- (UIPickerView *)firstTable{
    if (!_firstTable) {
        self.firstTable = [MyPickViews new];
    }
    return _firstTable;
}
- (UIPickerView *)secondTable{
    if (!_secondTable) {
        self.secondTable = [MyPickViews new];
    }
    return _secondTable;
}
- (UIPickerView *)thirdTable{
    if (!_thirdTable) {
        self.thirdTable = [MyPickViews new];
    }
    return _thirdTable;
}

- (id)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
        //获取当前日期,储存当前时间位置
        _indexArray = [self getNowDate:self.ScrollToDate];
        self.fistSelect = (int)[_indexArray[0] integerValue];
        self.secSelect = (int)[_indexArray[1] integerValue];
        self.thirdSelect = (int)[_indexArray[2] integerValue];
        
        [self configuesubViews];
        //网络请求方法
        _isMySelect = YES;
        [self networkWithURL:nil];
        
        [self addObserver:self forKeyPath:@"fistSelect" options:(NSKeyValueObservingOptionNew) context:nil];
        [self addObserver:self forKeyPath:@"secSelect" options:(NSKeyValueObservingOptionNew) context:nil];
        [self addObserver:self forKeyPath:@"thirdSelect" options:(NSKeyValueObservingOptionNew) context:nil];
    }
    return self;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
    [self networkWithURL:nil];
}

+ (void)showPickWithMakeSure:(void (^)(id, id, id))selectArea{
    dayClickSureBlock = selectArea;
    YTDatePick *pick = [Window viewWithTag:999];
    if (!pick) {
        pick = [[YTDatePick alloc] initWithFrame:CGRectMake(0, 0, Window_Root.width, Window_Root.height)];
        pick.tag = 999;
        [Window addSubview:pick];
    }
    else{
        //        pick.hidden = NO;
        [pick removeFromSuperview];
    }
}

- (void)networkWithURL:(NSString *)urlStr{
    NSString *path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:@"daysList"];
    NSFileManager *manager = [NSFileManager defaultManager];
    if ([manager fileExistsAtPath:path]) {
        NSArray *array = [NSArray arrayWithContentsOfFile:path];
        [self handleDataWithDic:array];
        //获取当前日期,储存当前时间位置
        _indexArray = [self getNowDate:self.ScrollToDate];
        NSLog(@"++++%d", (int)[_indexArray[0] integerValue]);
        NSLog(@"++++%d", (int)[_indexArray[1] integerValue]);
        NSLog(@"++++%d", (int)[_indexArray[2] integerValue]);
        //调整为现在的时间
        if (_isMySelect) {
            _isMySelect = NO;
            [_firstTable selectRow:(int)[_indexArray[0] integerValue] inComponent:0 animated:YES];
            [_secondTable selectRow:(int)[_indexArray[1] integerValue] inComponent:0 animated:YES];
            [_thirdTable selectRow:(int)[_indexArray[2] integerValue] inComponent:0 animated:YES];
        }
        
    }else{
        [self daysWithPath:path];
    }
}

bool LeepYear(int year){
    if (year % 100 == 0 ) {
        if (year % 400 == 0) {
            return 1;
        }
        return 0;
    }else if (year % 4 == 0){
        return 1;
    }else{
        return 0;
    }
}

- (void)daysWithPath:(NSString *)path{
    //年数组
    NSMutableArray *yearArray = [@[] mutableCopy];
    
    //设置年开始时间和结束年
    for (int i = UUPICKER_MINDATE; i <= UUPICKER_MAXDATE; i ++) {
        [yearArray addObject:@(i)];
    }
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSMutableArray *dataSource = [@[] mutableCopy];
        for (NSNumber *year in yearArray) {
            NSArray *temArray = @[@31, LeepYear(year.intValue) ? @29 : @28, @31, @30, @31, @30, @31, @31, @30, @31, @30, @31];
            NSMutableArray *monthArray = [@[] mutableCopy];
            for (int i = 1; i < 13; i ++) {
                
                NSMutableArray *daysArray = [@[] mutableCopy];
                
                for (int j = 1; j <= [temArray[i - 1] integerValue]; j ++) {
                    @autoreleasepool {
                        [daysArray addObject:@(j)];
                    }
                }
                
                @autoreleasepool {
                    NSDictionary *dic = @{@"month":@(i), @"daysList": daysArray};
                    [monthArray addObject:dic];
                }
            }
            [dataSource addObject:@{@"year" : year, @"monthList":monthArray}];
        }
        [dataSource writeToFile:path atomically:YES];
        
        dispatch_async(dispatch_get_main_queue(), ^{
            [self handleDataWithDic:dataSource];
            [_firstTable reloadAllComponents];
            [_secondTable reloadAllComponents];
            [_thirdTable reloadAllComponents];
            
            //获取当前日期,储存当前时间位置
            _indexArray = [self getNowDate:self.ScrollToDate];
            NSLog(@"++++%d", (int)[_indexArray[0] integerValue]);
            NSLog(@"++++%d", (int)[_indexArray[1] integerValue]);
            NSLog(@"++++%d", (int)[_indexArray[2] integerValue]);
            if (_isMySelect) {
                _isMySelect = NO;
                [_firstTable selectRow:(int)[_indexArray[0] integerValue] inComponent:0 animated:YES];
                [_secondTable selectRow:(int)[_indexArray[1] integerValue] inComponent:0 animated:YES];
                [_thirdTable selectRow:(int)[_indexArray[2] integerValue] inComponent:0 animated:YES];
            }
        });
    });
}

- (void)handleDataWithDic:(NSArray *)array{
    self.dataArr = [NSMutableArray arrayWithArray:array];
    [self.firstTable showPickViewWithFrame:CGRectMake(25, Window_Root.height - 220, Window_Root.width / 3.0 - 35, 150) delegate:self supView:self numberOfRowsInComponent:^NSInteger(NSInteger component) {
        return self.dataArr.count;
    } titleForRow:^UIView *(NSInteger row, NSInteger component) {
        NSDictionary *model = self.dataArr[row];
        UILabel *label = [[UILabel alloc] init];
        label.text = [NSString stringWithFormat:@"%@年", model[@"year"]];
        label.textAlignment = NSTextAlignmentCenter;
        return label;
    } didSelectRow:^(NSInteger row, NSInteger component) {
        self.fistSelect = row;
    }];
    
    [self.secondTable showPickViewWithFrame:CGRectMake(Window_Root.width / 3.0 + 15, Window_Root.height - 220, Window_Root.width / 3.0 - 35, 150) delegate:self supView:self numberOfRowsInComponent:^NSInteger(NSInteger component) {
        return 12;
    } titleForRow:^UIView *(NSInteger row, NSInteger component) {
        UILabel *label = [[UILabel alloc] init];
        label.text = [NSString stringWithFormat:@"%@月",@(row + 1).string];
        label.textAlignment = NSTextAlignmentCenter;
        return label;
    } didSelectRow:^(NSInteger row, NSInteger component) {
        self.secSelect = row;
    }];
    
    [self.thirdTable showPickViewWithFrame:CGRectMake(Window_Root.width / 3.0 * 2 , Window_Root.height - 220, Window_Root.width / 3.0 - 35, 150) delegate:self supView:self numberOfRowsInComponent:^NSInteger(NSInteger component) {
        NSArray *monthDic = self.dataArr[self.fistSelect][@"monthList"];
        NSArray *dayList = monthDic[self.secSelect][@"daysList"];
        return dayList.count;
        
    } titleForRow:^UIView *(NSInteger row, NSInteger component) {
        NSArray *monthDic = self.dataArr[self.fistSelect][@"monthList"];
        NSArray *dayList = monthDic[self.secSelect][@"daysList"];
        
        UILabel *label = [[UILabel alloc] init];
        label.text = [NSString stringWithFormat:@"%@日", ((NSNumber *)dayList[row]).string];
        label.textAlignment = NSTextAlignmentCenter;
        return label;
    } didSelectRow:^(NSInteger row, NSInteger component) {
        
    }];
}
- (void)configuesubViews{
    UIView *back = [[UIView alloc] initWithFrame:CGRectMake(20, Window_Root.height - 240, Window_Root.width - 50, 168)];
    back.backgroundColor = [UIColor whiteColor];
    back.layer.cornerRadius = 3;
    back.clipsToBounds = YES;
    [self addSubview:back];
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, Window_Root.width-50, 40)];
    label.textAlignment = NSTextAlignmentCenter;
    label.text = @"选择时间";
    label.font = [UIFont systemFontOfSize:18.0];
    [back addSubview:label];
    
    [self createButtonWithFrame:CGRectMake(20, self.bounds.size.height - 60, self.bounds.size.width / 2 - 30, 42) title:@"取 消" action:@selector(cancleClick)];
    
    [self createButtonWithFrame:CGRectMake(self.bounds.size.width / 2 , self.bounds.size.height - 60, self.bounds.size.width / 2 - 30, 42) title:@"确 定" action:@selector(makeSure)];
}

- (void)createButtonWithFrame:(CGRect )rect title:(NSString *)title action:(SEL)acrion{
    UIButton *cancleBtn = [UIButton buttonWithType:UIButtonTypeSystem];
    cancleBtn.frame = rect;
    [cancleBtn setTitle:title forState:(UIControlStateNormal)];
    cancleBtn.backgroundColor = [UIColor whiteColor];
    [cancleBtn setTitleColor:kColorNAVI_BULE forState:(UIControlStateNormal)];
    cancleBtn.layer.cornerRadius = 3;
    cancleBtn.clipsToBounds = YES;
    [cancleBtn addTarget:self action:acrion forControlEvents:(UIControlEventTouchUpInside)];
    [self addSubview:cancleBtn];
}
/**
 *  取消
 */
- (void)cancleClick{
    YTDatePick *pick = [Window viewWithTag:999];
    //    pick.hidden = YES;
    [pick removeFromSuperview];
    
    [[NSNotificationCenter defaultCenter] postNotificationName:@"setInfor" object:nil];
}
/**
 *  确定
 */
- (void)makeSure{
    NSString *year = self.dataArr[self.fistSelect][@"year"];
    
    NSArray *monthDic = self.dataArr[self.fistSelect][@"monthList"];
    NSArray *dayList = monthDic[self.secSelect][@"daysList"];
    NSString *month = [NSString stringWithFormat:@"%ld", (long)[self.secondTable selectedRowInComponent:0] + 1];
    NSString *day = dayList[[self.thirdTable selectedRowInComponent:0]];
    
    dayClickSureBlock(@(year.integerValue).string, @(month.integerValue).string, @(day.integerValue).string);
    NSLog(@"%@%@%@", @(year.integerValue).string, @(month.integerValue).string, @(day.integerValue).string);
    [self cancleClick];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"setCancleValueChanges" object:nil];
}

//获取当前时间解析及位置
- (NSArray *)getNowDate:(NSDate *)date
{
    NSDate *dateShow;
    if (date) {
        dateShow = date;
    }else{
        dateShow = [NSDate date];
    }
    YTDatePicker_DateModel *model = [[YTDatePicker_DateModel alloc]initWithDate:dateShow];
    yearIndex = [model.year intValue]-UUPICKER_MINDATE;
    monthIndex = [model.month intValue]-1;
    dayIndex = [model.day intValue]-1;
    NSNumber *year   = [NSNumber numberWithInteger:yearIndex];
    NSNumber *month  = [NSNumber numberWithInteger:monthIndex];
    NSNumber *day    = [NSNumber numberWithInteger:dayIndex];
    return @[year,month,day];
}

@end

参考博客

Apple开发者中心-Picker
iOS自定义日期、时间、城市选择器
菜鸟教程-IOS选择器

标签:NSInteger,pickerView,return,UIPickerView,component,self,IOS,日期,选择器
来源: https://www.cnblogs.com/EdmunddzzzzzZ/p/14944166.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有