iOS学习专题上海快风信息科技有限公司 ios 开发资料

iOS 年月日时分日期选择器

2016-11-29  本文已影响15974人  弹簧有弹力

在做公司项目的时候,选择时间的时候有这样一个需求,可以选择年月日时分这个时间,分有5分钟的间隔,这样子系统的UIDatePickerView就不能用了,好吧,既然有这个需求,咱也不能说这个不能做,不能用UIDatePickerView自带的时间选择。 那就用UIPickerView来写。

Alt text
Alt text

控制器的调用

#import "ViewController.h"

#import "THDatePickerView.h"

@interface ViewController () <THDatePickerViewDelegate>
@property (weak, nonatomic) IBOutlet UILabel *timerLbl;
@property (weak, nonatomic) THDatePickerView *dateView;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
   // 创建
    THDatePickerView *dateView = [[THDatePickerView alloc] initWithFrame:self.view.bounds];
   // 设置代理
    dateView.delegate = self;
   // 设置标题
    dateView.title = @"请选择时间";
    [self.view addSubview:dateView];
    self.dateView = dateView;
}

// 显示
- (IBAction)timerBrnClick:(id)sender {
    [self.dateView show];
}

#pragma mark - THDatePickerViewDelegate
/**
 保存按钮代理方法
 
 @param timer 选择的数据
 */
- (void)datePickerViewSaveBtnClickDelegate:(NSString *)timer {
    NSLog(@"保存点击");
    self.timerLbl.text = timer;
}

/**
 取消按钮代理方法
 */
- (void)datePickerViewCancelBtnClickDelegate {
    NSLog(@"取消点击");
}

具体实现THDatePickerView.h文件

@protocol THDatePickerViewDelegate <NSObject>

/**
 保存按钮代理方法
 
 @param timer 选择的数据
 */
- (void)datePickerViewSaveBtnClickDelegate:(NSString *)timer;

/**
 取消按钮代理方法
 */
- (void)datePickerViewCancelBtnClickDelegate;

@end

@interface THDatePickerView : UIView

@property (copy, nonatomic) NSString *title;
@property (weak, nonatomic) id <THDatePickerViewDelegate> delegate;

/// 显示
- (void)show;

具体实现THDatePickerView.m文件

@property (strong, nonatomic) UIView *dataView; // 容器view
@property (strong, nonatomic) UIPickerView *pickerView; // 选择器
@property (strong, nonatomic) UIView *toolView; // 工具条
@property (strong, nonatomic) UILabel *titleLbl; // 标题

@property (strong, nonatomic) NSMutableArray *dataArray; // 数据源
@property (copy, nonatomic) NSString *selectStr; // 选中的时间


@property (strong, nonatomic) NSMutableArray *yearArr; // 年数组
@property (strong, nonatomic) NSMutableArray *monthArr; // 月数组
@property (strong, nonatomic) NSMutableArray *dayArr; // 日数组
@property (strong, nonatomic) NSMutableArray *hourArr; // 时数组
@property (strong, nonatomic) NSMutableArray *minuteArr; // 分数组
@property (strong, nonatomic) NSArray *timeArr; // 当前时间数组

@property (copy, nonatomic) NSString *year; // 选中年
@property (copy, nonatomic) NSString *month; //选中月
@property (copy, nonatomic) NSString *day; //选中日
@property (copy, nonatomic) NSString *hour; //选中时
@property (copy, nonatomic) NSString *minute; //选中分
- (void)show {
    [UIView animateWithDuration:0.25 animations:^{
        self.year = self.timeArr[0];
        self.month = self.timeArr[1];
        self.day = self.timeArr[2];
        self.hour = self.timeArr[3];
        self.minute = self.minuteArr[self.minuteArr.count / 2];
        
        CGRect frame = self.dataView.frame;
        frame.origin.y = self.frame.size.height - 300;
        self.dataView.frame = frame;
        
        self.hidden = NO;
    } completion:^(BOOL finished) {
        
        [self.pickerView selectRow:[self.yearArr indexOfObject:self.year] inComponent:0 animated:YES];
        /// 重新格式化转一下,是因为如果是09月/日/时,数据源是9月/日/时,就会出现崩溃
        [self.pickerView selectRow:[self.monthArr indexOfObject:[NSString stringWithFormat:@"%ld月", [self.month integerValue]]] inComponent:1 animated:YES];
        [self.pickerView selectRow:[self.dayArr indexOfObject:[NSString stringWithFormat:@"%ld日", [self.day integerValue]]] inComponent:2 animated:YES];
        [self.pickerView selectRow:[self.hourArr indexOfObject:[NSString stringWithFormat:@"%ld时", [self.hour integerValue]]] inComponent:3 animated:YES];
        [self.pickerView selectRow:self.minuteArr.count / 2 inComponent:4 animated:YES];
    }];
}

pragma mark - 点击方法

/// 保存按钮点击方法

- (void)saveBtnClick {
    NSLog(@"点击了保存");
    
    [UIView animateWithDuration:0.25 animations:^{
        
        CGRect frame = self.dataView.frame;
        frame.origin.y = self.frame.size.height;
        self.dataView.frame = frame;
        
    } completion:^(BOOL finished) {
        
        self.hidden = YES;
        NSInteger index = [self compareDate:[self.timeArr componentsJoinedByString:@","] withDate:[NSString stringWithFormat:@"%@,%@,%@,%@,%@", self.year, self.month, self.day, self.hour, self.minute]];
        switch (index) {
            case -1: {
                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"面试时间小于当前时间,请重新选择" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
                [alert show];
            } break;
            case 0:
            case 1: {
                if (self.minute.length == 2) {
                    self.selectStr = [NSString stringWithFormat:@"%ld-%ld-%ld  %ld : 0%ld", [self.year integerValue], [self.month integerValue], [self.day integerValue], [self.hour integerValue], [self.minute integerValue]];
                } else {
                    self.selectStr = [NSString stringWithFormat:@"%ld-%ld-%ld  %ld : %ld", [self.year integerValue], [self.month integerValue], [self.day integerValue], [self.hour integerValue], [self.minute integerValue]];
                }
                if ([self.delegate respondsToSelector:@selector(datePickerViewSaveBtnClickDelegate:)]) {
                    [self.delegate datePickerViewSaveBtnClickDelegate:self.selectStr];
                }
            } break;
            default: break;
        }
    }];
    
}

/// 取消按钮点击方法

- (void)cancelBtnClick {
    NSLog(@"点击了取消");
    
    [UIView animateWithDuration:0.25 animations:^{
        
        CGRect frame = self.dataView.frame;
        frame.origin.y = self.frame.size.height;
        self.dataView.frame = frame;
        
    } completion:^(BOOL finished) {
        
        self.hidden = YES;
        if ([self.delegate respondsToSelector:@selector(datePickerViewCancelBtnClickDelegate)]) {
            [self.delegate datePickerViewCancelBtnClickDelegate];
        }
    }];
}

/// 点击背景消失

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [super touchesBegan:touches withEvent:event];
    [self cancelBtnClick];
}

pragma mark - UIPickerViewDelegate and UIPickerViewDataSource

/// UIPickerView返回多少组

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
    return self.dataArray.count;
}

/// UIPickerView返回每组多少条数据

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
    return  [self.dataArray[component] count];
}

/// UIPickerView选择哪一行

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
    switch (component) {
        case 0: { // 年
            if ([self.yearArr[row] integerValue] < [self.timeArr[component] integerValue]) {
                [pickerView selectRow:[self.dataArray[component] indexOfObject:self.timeArr[component]] inComponent:component animated:YES];
            } else {
                self.year = self.yearArr[row];
                [self.pickerView selectRow:[self.monthArr indexOfObject:self.timeArr[1]] inComponent:1 animated:YES];
                [self.pickerView selectRow:[self.dayArr indexOfObject:self.timeArr[2]] inComponent:2 animated:YES];
                [self.pickerView selectRow:[self.hourArr indexOfObject:self.timeArr[3]] inComponent:3 animated:YES];
            }
        } break;
        case 1: { // 月
            // 如果选择年大于当前年 就直接赋值月
            if ([self.year integerValue] > [self.timeArr[0] integerValue]) {
                self.month = self.monthArr[row];
            // 如果选择的年等于当前年,就判断月份
            } else if ([self.year integerValue] == [self.timeArr[0] integerValue]) {
                // 如果选择的月份小于当前月份 就刷新到当前月份
                if ([self.monthArr[row] integerValue] < [self.timeArr[component] integerValue]) {
                    [pickerView selectRow:[self.dataArray[component] indexOfObject:self.timeArr[component]] inComponent:component animated:YES];
                // 如果选择的月份大于当前月份,就直接赋值月份
                } else {
                    self.month = self.monthArr[row];
                }
            }
        } break;
        case 2: { // 日
            // 如果选择年大于当前年 就直接赋值日
            if ([self.year integerValue] > [self.timeArr[0] integerValue]) {
                self.day = self.dayArr[row];
                // 如果选择的年等于当前年,就判断月份
            } else if ([self.year integerValue] == [self.timeArr[0] integerValue]) {
                // 如果选择的月份大于当前月份 就直接复制
                if ([self.month integerValue] > [self.timeArr[1] integerValue]) {
                    self.day = self.dayArr[row];
                // 如果选择的月份等于当前月份,就判断日
                } else if ([self.month integerValue] == [self.timeArr[1] integerValue]) {
                    // 如果选择的日小于当前日,就刷新到当前日
                    if ([self.dayArr[row] integerValue] < [self.timeArr[component] integerValue]) {
                        [pickerView selectRow:[self.dataArray[component] indexOfObject:self.timeArr[component]] inComponent:component animated:YES];
                    // 如果选择的日大于当前日,就复制日
                    } else {
                        self.day = self.dayArr[row];
                    }
                }
            }
        } break;
        case 3: { // 时
            // 如果选择年大于当前年 就直接赋值时
            if ([self.year integerValue] > [self.timeArr[0] integerValue]) {
                self.hour = self.hourArr[row];
                // 如果选择的年等于当前年,就判断月份
            } else if ([self.year integerValue] == [self.timeArr[0] integerValue]) {
                // 如果选择的月份大于当前月份 就直接复制时
                if ([self.month integerValue] > [self.timeArr[1] integerValue]) {
                    self.hour = self.hourArr[row];
                    // 如果选择的月份等于当前月份,就判断日
                } else if ([self.month integerValue] == [self.timeArr[1] integerValue]) {
                    // 如果选择的日大于当前日,就直接复制时
                    if ([self.day integerValue] > [self.timeArr[2] integerValue]) {
                        self.hour = self.hourArr[row];
                    // 如果选择的日等于当前日,就判断时
                    } else if ([self.day integerValue] == [self.timeArr[2] integerValue]) {
                        // 如果选择的时小于当前时,就刷新到当前时
                        if ([self.hourArr[row] integerValue] < [self.timeArr[3] integerValue]) {
                            [pickerView selectRow:[self.dataArray[component] indexOfObject:self.timeArr[component]] inComponent:component animated:YES];
                        // 如果选择的时大于当前时,就直接赋值
                        } else {
                            self.hour = self.hourArr[row];
                        }
                    }
                }
            }
        } break;
        case 4: { // 分
            // 如果选择年大于当前年 就直接赋值时
//            if ([self.year integerValue] > [self.timeArr[0] integerValue]) {
                self.minute = self.minuteArr[row];
//                // 如果选择的年等于当前年,就判断月份
//            } else if ([self.year integerValue] == [self.timeArr[0] integerValue]) {
//                // 如果选择的月份大于当前月份 就直接复制时
//                if ([self.month integerValue] > [self.timeArr[1] integerValue]) {
//                    self.minute = self.minuteArr[row];
//                    // 如果选择的月份等于当前月份,就判断日
//                } else if ([self.month integerValue] == [self.timeArr[1] integerValue]) {
//                    // 如果选择的日大于当前日,就直接复制时
//                    if ([self.day integerValue] > [self.timeArr[2] integerValue]) {
//                        self.minute = self.minuteArr[row];
//                        // 如果选择的日等于当前日,就判断时
//                    } else if ([self.day integerValue] == [self.timeArr[2] integerValue]) {
//                        // 如果选择的时大于当前时,就直接赋值
//                        if ([self.hour integerValue] > [self.timeArr[3] integerValue]) {
//                            self.minute = self.minuteArr[row];
//                        // 如果选择的时等于当前时,就判断分
//                        } else if ([self.hour integerValue] == [self.timeArr[3] integerValue]) {
//                            // 如果选择的分小于当前分,就刷新分
//                            if ([self.minuteArr[row] integerValue] < [self.timeArr[4] integerValue]) {
//                                [pickerView selectRow:[self.dataArray[component] indexOfObject:self.timeArr[component]] inComponent:component animated:YES];
//                            // 如果选择分大于当前分,就直接赋值
//                            } else {
//                                self.minute = self.minuteArr[row];
//                            }
//                        }
//                    }
//                }
//            }
        } break;
        default: break;
    }
}

/// UIPickerView返回每一行数据

- (nullable NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{
    return  self.dataArray[component][row];
}

/// UIPickerView返回每一行的高度

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

/// UIPickerView返回每一行的View

-(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view{
    UILabel *myView = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, self.frame.size.width, 44)];
    myView.font = [UIFont systemFontOfSize:15];
    myView.textAlignment = NSTextAlignmentCenter;
    myView.text = self.dataArray[component][row];
    return myView;
}

// 比较选择的时间是否小于当前时间

- (int)compareDate:(NSString *)date01 withDate:(NSString *)date02{
    int ci;
    NSDateFormatter *df = [[NSDateFormatter alloc]init];
    [df setDateFormat:@"yyyy年,MM月,dd日,HH时,mm分"];
    NSDate *dt1 = [[NSDate alloc] init];
    NSDate *dt2 = [[NSDate alloc] init];
    dt1 = [df dateFromString:date01];
    dt2 = [df dateFromString:date02];
    NSComparisonResult result = [dt1 compare:dt2];
    switch (result) {
            //date02比date01大
        case NSOrderedAscending: ci=1;break;
            //date02比date01小
        case NSOrderedDescending: ci=-1;break;
            //date02=date01
        case NSOrderedSame: ci=0;break;
        default: NSLog(@"erorr dates %@, %@", dt2, dt1);break;
    }
    return ci;
}

好了就这样子实现了。主要是时间选择的时候,判断年月日时的时候比较烦,分的话,因为获取的当前时间和self.minuteArr数组里面的时间不通。所以不做判断,但是代码就是这样子了。
欢迎来来我的github网址下来dome 如果觉得好麻烦请star

2018-3-12 更新

  1. 可以选择以前的时间
    2.支持自定义当前时间
    3.支持修改分钟时间间隔
上一篇 下一篇

猜你喜欢

热点阅读