iOS UIPickerView的使用---自定义时间选择器

概述

自定义时间选择器,难点在于时间数据的获取,主要是在时间进位的时候,数据可能会大范围的改变,列如:
在59分时,进位后下一分钟是0分,此时小时值会加1,如果上一分钟小时数为23,则小时数据进位后变成第二天的0点,如果上一分钟天数是月底最后一天,则进位后月份也会跟着进位加1,如果上一分钟月份数为12,则进位后月份数会变成1月,此时年份数加1。
另外一个注意事项是,时间是时时刻变化的,所以要保证时间选择器上的数据正确有效,需要让它过一段时间间隔就刷新重新获取数据,然后刷新控件

界面效果图

代码

数据获取的关键代码
-(void)getData{
    /*
     获取时间数据分为两种情况,一种是常规数据,如一个月28/29/30/31天,一天24小时,一小时60分钟等,这个数据很好获取
     另一种情况是当前的数据,当前时间数据比较复杂,前提条件:分钟只需要取10钟一间隔得数据即:0、10、20、30、40、50,这样获取数据的时候需要在当前时间加10分钟,这样的话 在50~59分,小时数据是没有当前的小时值可选的;在23时50~59分,当前天数是不可选的;在每月的最后一天和每年的最后一天都有类似的特殊情况,同时需要每个一分钟更新一次当前的时间的数据
     */
    //在当前时间加10分钟,然后获取年月日时分的值
    NSDate * date = [NSDate dateWithTimeIntervalSinceNow:60*10];//提前10分钟
    NSCalendar * canlendar = [NSCalendar currentCalendar];
    NSInteger unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
    NSDateComponents * components = [canlendar components:unitFlags fromDate:date];
    NSInteger nowY = [components year];
    NSInteger nowM = [components month];
    NSInteger nowD = [components day];
    NSInteger nowH = [components hour];
    NSInteger nowF = [components minute];
    //给当前值赋值--这些值主要是用于时间选择器的第一次打开时显示当前时间
    self.defaultYear = [components year];
    self.defaultMonth = [components month];
    self.defaultDay = [components day];
    self.defaultHour = [components hour];
    NSLog(@"%ld",[components minute]);
    self.defaultMinute = ([components minute]/10)*10 ;
    //获取当前月的天数
    NSRange range = [canlendar rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:date];
    NSUInteger numberOfDaysInMonth = range.length;
    NSMutableArray * nowPickerViewDataArr0 = [[NSMutableArray alloc] init];
    NSMutableArray * nowPickerViewDataArr1 = [[NSMutableArray alloc] init];
    NSMutableArray * nowPickerViewDataArr2 = [[NSMutableArray alloc] init];
    NSMutableArray * nowPickerViewDataArr3 = [[NSMutableArray alloc] init];
    NSMutableArray * nowPickerViewDataArr4 = [[NSMutableArray alloc] init];
    //获取当前分钟数
    if (nowF >= 50) {//大于50分到59之间分钟数需要特殊处理
        self.defaultMinute = 0;
        self.defaultHour+=1;
        if (self.defaultHour == 24) {
            self.defaultHour = 0;
        }
        for (int i = 0; i < 6; i++) {
            [nowPickerViewDataArr4 addObject:[NSNumber numberWithInteger:i*10]];
        }
    }else{//小于50分,则只获取当前可选的分钟值
        for (NSInteger i = self.defaultMinute/10; i < 6; i++) {
            [nowPickerViewDataArr4 addObject:[NSNumber numberWithInteger:i*10]];
        }
    }
    //获取当前小时数
    if (nowH >= 23&&nowH>=50) {//23点50分到59之间,当前小时数需要特殊处理
        self.defaultHour+=1;
        self.defaultDay+=1;
        if (self.defaultDay >numberOfDaysInMonth) {
            self.defaultDay = 1;
        }
        for (int i = 0; i < 24; i++) {
            [nowPickerViewDataArr3 addObject:[NSNumber numberWithInteger:i]];
        }
    }else{//
        for (NSInteger i = self.defaultHour; i < 24; i++) {
            [nowPickerViewDataArr3 addObject:[NSNumber numberWithInteger:i]];
        }
    }
    //获取当前日数
    if (nowD >= numberOfDaysInMonth&&nowH >= 23&&nowH>=50) {//每月最后一天23点50分到59之间,当前小时数需要特殊处理
        self.defaultDay+=1;
        self.defaultMonth+=1;
        if (self.defaultMonth >12) {
            self.defaultMonth = 1;
        }
        for (int i = 1; i <= numberOfDaysInMonth; i++) {
            [nowPickerViewDataArr2 addObject:[NSNumber numberWithInteger:i]];
        }
    }else{//
        for (NSInteger i = self.defaultDay; i <= numberOfDaysInMonth; i++) {
            [nowPickerViewDataArr2 addObject:[NSNumber numberWithInteger:i]];
        }
    }
    //获取当前月份数
    if (nowM >= 12&&nowD >= numberOfDaysInMonth&&nowH >= 23&&nowH>=50) {//每年12月最后一天23点50分到59之间,当前小时数需要特殊处理
        self.defaultMonth+=1;
        self.defaultYear+=1;
        if (self.defaultYear >nowY) {
            self.defaultYear = nowY+1;
        }
        for (int i = 1; i <= 12; i++) {
            [nowPickerViewDataArr1 addObject:[NSNumber numberWithInteger:i]];
        }
    }else{//
        for (NSInteger i = self.defaultMonth; i <= 12; i++) {
            [nowPickerViewDataArr1 addObject:[NSNumber numberWithInteger:i]];
        }
    }
    //获取年份
    for (int i = 0; i < 3; i++) {
        [nowPickerViewDataArr0 addObject:[NSNumber numberWithInteger:i+self.defaultYear]];
    }
    //将当前时间的数据存到数组
    [self.nowPickerViewDataArr addObject:nowPickerViewDataArr0];
    [self.nowPickerViewDataArr addObject:nowPickerViewDataArr1];
    [self.nowPickerViewDataArr addObject:nowPickerViewDataArr2];
    [self.nowPickerViewDataArr addObject:nowPickerViewDataArr3];
    [self.nowPickerViewDataArr addObject:nowPickerViewDataArr4];
    //获取常规数值
    NSMutableArray * pickerViewDataArr1 = [[NSMutableArray alloc] init];
    NSMutableArray * pickerViewDataArr2 = [[NSMutableArray alloc] init];
    NSMutableArray * pickerViewDataArr3 = [[NSMutableArray alloc] init];
    NSMutableArray * pickerViewDataArr4 = [[NSMutableArray alloc] init];
    //分钟
    for (int i = 0; i < 6; i++) {
        [pickerViewDataArr4 addObject:[NSNumber numberWithInteger:i*10]];
    }
    //小时
    for (NSInteger i = 0; i < 24; i++) {
        [pickerViewDataArr3 addObject:[NSNumber numberWithInteger:i]];
    }
    //天数
    for (NSInteger i = 1; i <= numberOfDaysInMonth; i++) {
        [pickerViewDataArr2 addObject:[NSNumber numberWithInteger:i]];
    }
    //月数
    for (NSInteger i = 1; i <= 12; i++) {
        [pickerViewDataArr1 addObject:[NSNumber numberWithInteger:i]];
    }
    [self.pickerViewDataArr addObject:nowPickerViewDataArr0];
    [self.pickerViewDataArr addObject:pickerViewDataArr1];
    [self.pickerViewDataArr addObject:pickerViewDataArr2];
    [self.pickerViewDataArr addObject:pickerViewDataArr3];
    [self.pickerViewDataArr addObject:pickerViewDataArr4];
}
pickerView返回行数的代理方法关键代码
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
    if (component == 0) {
        return [self.nowPickerViewDataArr[0] count];
    } else if(component == 1){
        if (self.selectRow0 == 0) {
            return [self.nowPickerViewDataArr[1] count];
        } else {
            return [self.pickerViewDataArr[1] count];
        }
    }else if (component ==2){
        if (self.selectRow0 == 0&&self.selectRow1 == 0) {
            return [self.nowPickerViewDataArr[2] count];
        } else {
            return [self.pickerViewDataArr[2] count];
        }
    }else if (component == 3){
        if (self.selectRow2 == 0&&self.selectRow1 == 0&&self.selectRow0 == 0) {
            return [self.nowPickerViewDataArr[3] count];
        } else {
            return [self.pickerViewDataArr[3] count];
        }
    }else{
        if (self.selectRow3 ==0&&self.selectRow2 == 0&&self.selectRow1 == 0&&self.selectRow0 == 0) {
            return [self.nowPickerViewDataArr[4] count];
        } else {
            return [self.pickerViewDataArr[4] count];
        }
    }
}
pickerView返回显示值的代理方法关键代码
-(UIView*)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view{
    //添加一个label
    UILabel * label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth/5, 30)];
    label.textColor = [UIColor grayColor];
    label.font = [UIFont systemFontOfSize:15];
    label.textAlignment = NSTextAlignmentLeft;
    //对每一列都需要做特殊和非特殊的判断,一遍给到正确的值
    if (component == 0) {
        label.text = [NSString stringWithFormat:@"%@",self.nowPickerViewDataArr[0][row]];
    } else if(component == 1){
        if (self.selectRow0 == 0) {
            label.text = [NSString stringWithFormat:@"%@",self.nowPickerViewDataArr[1][row]];
        } else {
            label.text = [NSString stringWithFormat:@"%@",self.pickerViewDataArr[1][row]];
        }
    }else if (component ==2){
        if (self.selectRow0 == 0&&self.selectRow1 == 0) {
            label.text = [NSString stringWithFormat:@"%@",self.nowPickerViewDataArr[2][row]];
        } else {
            label.text = [NSString stringWithFormat:@"%@",self.pickerViewDataArr[2][row]];
        }
    }else if (component == 3){
        if (self.selectRow2 == 0&&self.selectRow1 == 0&&self.selectRow0 == 0) {
            label.text = [NSString stringWithFormat:@"%@",self.nowPickerViewDataArr[3][row]];
        } else {
            label.text = [NSString stringWithFormat:@"%@",self.pickerViewDataArr[3][row]];
        }
    }else{
        if (self.selectRow3 ==0&&self.selectRow2 == 0&&self.selectRow1 == 0&&self.selectRow0 == 0) {
            label.text = [NSString stringWithFormat:@"%@",self.nowPickerViewDataArr[4][row]];
        } else {
            label.text = [NSString stringWithFormat:@"%@",self.pickerViewDataArr[4][row]];
        }
    }
    return label;
}
pickerView选择行的代理方法关键代码
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
    //获取选中的列数
    self.selectRow0 = [pickerView selectedRowInComponent:0];
    self.selectRow1 = [pickerView selectedRowInComponent:1];
    self.selectRow2 = [pickerView selectedRowInComponent:2];
    self.selectRow3 = [pickerView selectedRowInComponent:3];
    self.selectRow4 = [pickerView selectedRowInComponent:4];
    //先清空之前的数据,在重新获取数据
    self.pickerViewDataArr = nil;
    self.nowPickerViewDataArr = nil;
    [self getData];
    //刷新后面的列
    if (component == 0) {//选择完成后加载后面的列的数据但是不刷新当前列
        [pickerView reloadComponent:1];
        [pickerView reloadComponent:2];
        [pickerView reloadComponent:3];
        [pickerView reloadComponent:4];
    } else if(component == 1){
        [pickerView reloadComponent:2];
        [pickerView reloadComponent:3];
        [pickerView reloadComponent:4];
    }else if(component == 2){
        [pickerView reloadComponent:3];
        [pickerView reloadComponent:4];
    }else if(component == 3){
        [pickerView reloadComponent:4];
    }
}

详细代码看Demo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,401评论 25 707
  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,852评论 6 13
  • 废话不多说,直接上干货 ---------------------------------------------...
    小小赵纸农阅读 3,333评论 0 15
  • 穿过漫漫的黑夜 终究会抵达那个地方 见到那个人 有人会听你的故事 有人会懂你的喜和伤 你不要急 不管山再怎么高,路...
    虹岑阅读 201评论 2 1
  • 2017年10月18日 星期三 晴 晚上孩子放学回来,去自己房间看书了,做好饭我去叫他吃饭,吃饱饭儿子主...
    A燕子_fa10阅读 172评论 0 0