内容简介:前几天接到一个版本,里面包含了一个和滴滴预约用车选择时间的picker一样,需要选择当前时间的后面几天内的时间,包含了日期,小时和分钟数,分钟数的间隔是以10分钟为单位,如下图所示:当接到这个需求时,我的心里是有点小拒绝的,看着就是一个pickerView但是里面东西还是有的东西的,包含:个人认为,能自己做的尽量都少用三方库,减少对三方库的依赖,(PS:目前项目用了百度地图,iOS12删除了百度SDK用到的系统库,各种麻烦),所以决定自己造一个轮子。
前几天接到一个版本,里面包含了一个和滴滴预约用车选择时间的picker一样,需要选择当前时间的后面几天内的时间,包含了日期,小时和分钟数,分钟数的间隔是以10分钟为单位,如下图所示:
当接到这个需求时,我的心里是有点小拒绝的,看着就是一个pickerView但是里面东西还是有的东西的,包含:
- 时间数据源获取,获取当前时间到3天后。
- 自定义时间数据源,分钟时间刻度单位为10分钟,不足10分钟的向上取整。
- 选择当天对当前小时数据和分钟数据的处理。
- 选择当前小时情况下对分钟数据源的处理。
- pickerView自定义展示(颜色,字体大小)
个人认为,能自己做的尽量都少用三方库,减少对三方库的依赖,(PS:目前项目用了百度地图,iOS12删除了百度SDK用到的系统库,各种麻烦),所以决定自己造一个轮子。
过程
获取天数
这里采用NSDate的 dateWithTimeIntervalSinceNow
函数再转成字符串,值得一提的是 NSDateFormatter
,根据官方文档的描述:
Creating a date formatter is not a cheap operation. If you are likely to use a formatter frequently, it is typically more efficient to cache a single instance than to create and dispose of multiple instances. One approach is to use a static variable.
创建一个formatter实例的代价是比较高,频繁使用时要考虑缓存,个人的做法是:
+ (void)load { if (!_dateFormatter) { _dateFormatter = [[NSDateFormatter alloc] init]; [_dateFormatter setDateFormat:@"YYYY-MM-dd HH:mm"]; } } 复制代码
保证只创建一个NSDateFormatter实例,关于 +load
不做多说,想了解更多的可以看看之前的 Runtime源码 +load 和 +initialize
for (NSInteger i = 0; i < kDays; i++) { NSString *dateString = [self distanceDate:beginTime aDay:i];//获取第i天的日期 NSString *week = [self currentWeek:dateString type:NO];//获取星期几 } 复制代码
这里用到了
static NSInteger const kDays = 3;//从今天起能选择多少天 默认3天 复制代码
因为#define在编译的预处理阶段有一个宏替换操作,大量地使用#define会拖慢编译速度,而且宏没有类型,不做任何类型检查。Apple官方也是使用了更多的const。
分钟数向上取整
需求是当分钟数不为整10分钟时,向上取整,比如,16->20,41->50,所以对初始的数据源还有一步向上取整的操作:
NSString *beginTime = [self getTimerAfterCurrentTime:kBenginTimeDely];//开始时间(也就是当前时间20分钟后) NSInteger currentMin = [self getMString:beginTime]; if (currentMin % kTimeInterval != 0) { beginTime = [self getTimerAfterTime:beginTime periodMin:(kTimeInterval - currentMin % kTimeInterval)];//开始时间向上取整 } 复制代码
这里把这三个数据抽取出来,提高灵活性,比如天数要5天之后or时间间隔要改成5分钟or最早时间是30分钟后这里只需要修改对应常量即可。
选中数据的处理
第一次的做法是在 - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
中切换日期或者小时的时候重新计算数据源,但是发现这样的效果并不好,有明显的卡顿现象,想起来这样的真的是很愚蠢的办法。应该初始化的时候计算好数据源,而不是每次都重新计算。
在切换日期或者小时数的时候切换数据源,具体实现:
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { if (component == 0) { return self.dataSourceModel.dateArray.count; } else if (component == 1) { if (self.selectedDateIndex == 0) {//选中的今天 return self.dataSourceModel.todayHourArray.count; } else { return self.dataSourceModel.hourArray.count; } } else { if (self.selectedHourIndex == 0 && self.selectedDateIndex == 0) {//选中的当天的第一个小时 return self.dataSourceModel.todayMinuteArray.count; } else { return self.dataSourceModel.minuteArray.count; } } } 复制代码
关于数据源的计算,比较直观,这里就不贴出来了,详情请看 QFDatePickerView 中 QFTimerUtil
文件 + (QFTimerDataSourceModel *)configDataSource
方法
pickerView自定义展示
可以直接通过默认的代理方法 - (nullable NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component __TVOS_PROHIBITED
实现日期显示,但是这样的展示效果却和设计图差距较大,所以实现了 - (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UILabel *)recycledLabel
自定义展示:
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UILabel *)recycledLabel { if (!recycledLabel) { recycledLabel = [[UILabel alloc] init]; } recycledLabel.textAlignment = NSTextAlignmentCenter; [recycledLabel setFont:[UIFont systemFontOfSize:18]]; recycledLabel.textColor = [UIColor colorWithRed:34.0f / 255.0f green:34.0f / 255.0f blue:34.0f / 255.0f alpha:1.0f]; ... recycledLabel.text = minModel.showMinuteString; return recycledLabel; } 复制代码
使用方式
手动拖入文件夹 或者 pod 'QFDatePicker'
导入QFTimerPicker头文件,在对应的地方调用picker的初始化方法和show方法:
/** 初始化时间选择 @param block 回调block 参数即是选择的日期 @return 时间选择器实例 */ - (instancetype)initWithResponse:(ReturnBlock)block; /** 初始化时间选择 @param superView 时间选择器的父View,若为空,将时间选择器加载在window上面 @param block 回调block 参数即是选择的日期 @return 时间选择器实例 */ - (instancetype)initWithSuperView:(UIView *)superView response:(ReturnBlock)block; 复制代码
注释比较清楚了,通过 superView
参数,控制这个picker加载在什么视图上,当其为空的时候加载在window上。
选中的时间再block中回调(PS:这里如果把picker设置为属性时,考虑循环强引用的问题)
具体调用案例:
QFTimerPicker *picker = [[QFTimerPicker alloc]initWithSuperView:self.view response:^(NSString *selectedStr) { NSLog(@"%@",selectedStr); [sender setTitle:selectedStr forState:UIControlStateNormal]; }]; [picker show]; 复制代码
以上所述就是小编给大家介绍的《iOS仿滴滴预约用车时间选择器》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 详解:易到用车如何被黑客“开”走了车
- 东风商用车 – IT服务运营中枢一期
- 直播预约 | 揭秘微信支付背后的数据库技术
- 突发流量洪峰应对之道:疫情期间京东口罩预约抢购系统优化
- 魔视智能发布乘用车前视一体机,已实现量产
- 直播预约 | 在生产环境中,阿里云如何构建高性能云原生容器网络?
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。