iOS 年月日时分日期选择器
2016-11-29 本文已影响15974人
弹簧有弹力
在做公司项目的时候,选择时间的时候有这样一个需求,可以选择年月日时分这个时间,分有5分钟的间隔,这样子系统的UIDatePickerView就不能用了,好吧,既然有这个需求,咱也不能说这个不能做,不能用UIDatePickerView自带的时间选择。 那就用UIPickerView来写。
Alt textAlt 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 更新
- 可以选择以前的时间
2.支持自定义当前时间
3.支持修改分钟时间间隔