之前开发也遇到过酒店,火车票日历,我用了一款第三方软件,前期还行,随着后期功能(业务)增多,就不好使了,特别是那个循环架构,年 月 日这种的,修改起来特别麻烦。
新增业务例如:
1、价格日历,景点价格日历,机票价格日历
2、基地日历,我们基地价格分批次的 1-8天 110元/天,9-20天100 ,21-30天90,这就要求选择开始日期后,重新刷新数据,只能选择天数区域内的时间。
3、活动日历,活动不是每天搞,隔三差五的,一句话就是可点不可点,传日期输入,处理后展示出来。
#define MSS_SCREEN_WIDTH ([UIScreen mainScreen].bounds.size.width)
#define MSS_SCREEN_HEIGHT ([UIScreen mainScreen].bounds.size.height)
#define MSS_UTILS_COLORRGB(r,g,b) [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1]
#define MSS_Iphone6Scale(x) ((x) * MSS_SCREEN_WIDTH / 375.0f)
#define MSS_ONE_PIXEL (1.0f / [[UIScreen mainScreen] scale])
/*定义属性*/
// 选择点击颜色
#define SelectedColor [UIColor cyanColor]
// 被选中间颜色
#define SelMiddleColor [UIColor greenColor]
// DateLabel默认文字颜色
#define MSS_TextColor [UIColor blackColor]
// DateLabel选中时的背景色
#define MSS_SelectBackgroundColor MSS_UTILS_COLORRGB(29, 154, 72)
// DateLabel选中后文字颜色
#define MSS_SelectTextColor [UIColor whiteColor]
// SubLabel文字颜色
#define MSS_SelectSubLabelTextColor MSS_UTILS_COLORRGB(29, 154, 180);
// SubLabel选中开始文字
#define MSS_SelectBeginText @"开始"
// SubLabel选中结束文字
#define MSS_SelectEndText @"结束"
// 节日颜色
#define MSS_HolidayTextColor [UIColor purpleColor]
// 周末颜色
#define MSS_WeekEndTextColor [UIColor redColor]
// 不可点击文字颜色
#define MSS_TouchUnableTextColor MSS_UTILS_COLORRGB(150, 150, 150)
// 周视图高度
#define MSS_WeekViewHeight 60
// headerView线颜色
#define MSS_HeaderViewLineColor [UIColor lightGrayColor]
// headerView文字颜色
#define MSS_HeaderViewTextColor [UIColor blackColor]
// headerView高度
#define MSS_HeaderViewHeight 50
// 弹出层文字颜色
#define MSS_CalendarPopViewTextColor [UIColor whiteColor]
// 弹出层背景颜色
#define MSS_CalendarPopViewBackgroundColor [UIColor blackColor]
typedef NS_ENUM(NSInteger, MSSCalendarViewControllerType)
{
MSSCalendarViewControllerLastType = 0,// 只显示当前月之前
MSSCalendarViewControllerMiddleType,// 前后各显示一半
MSSCalendarViewControllerNextType// 只显示当前月之后
};
typedef NS_ENUM(NSInteger, MSSCalendarWithUserType)
{
MSSCalendarHotelType = 0, // 酒店 入住 --- 离店
MSSCalendarTrainType, // 火车票,飞机票,单选无价格
MSSCalendarAplaceType, // 基地 价格
MSSCalendarSecnicType, // 景点 价格
MSSCalendarPlaneType, // 机票
MSSCalendarActivityType // 活动,线路
};
可以自定义以上属性,什么颜色,类型什么的。
核心思路就在这块,简单明了,传的有一个参数limitMonth,显示几个月的数据,MSSCalendarViewControllerNextType就是今天以后, components.month -= 1;获取当前月份减一,不要问为什么减一,打隔断点看看就知道了,MSSCalendarViewControllerLastType这是今天以前的limitMonth月的日期。
- (NSArray *)getCalendarDataSoruceWithLimitMonth:(NSInteger)limitMonth type:(MSSCalendarViewControllerType)type
{
NSMutableArray *resultArray = [[NSMutableArray alloc]init];
NSDateComponents *components = [self dateToComponents:_todayDate];
components.day = 1;
if(type == MSSCalendarViewControllerNextType)
{
components.month -= 1;
}
else if(type == MSSCalendarViewControllerLastType)
{
components.month -= limitMonth;
}
else
{
components.month -= (limitMonth + 1) / 2;
}
NSInteger i = 0;
for(i = 0;i < limitMonth;i++)
{
components.month++;
MSSCalendarHeaderModel *headerItem = [[MSSCalendarHeaderModel alloc]init];
NSDate *date = [self componentsToDate:components];
[_dateFormatter setDateFormat: @"yyyy年MM月"];
NSString *dateString = [_dateFormatter stringFromDate:date];
headerItem.headerText = dateString;
headerItem.calendarItemArray = [self getCalendarItemArrayWithDate:date section:i]; // section就是当月数据页面的位置
[resultArray addObject:headerItem];
}
return resultArray;
}
一共limitMonth个月,从第一个月开始排序,整理数组。下面是每一个单独月的日期数据
// 得到每一天的数据源
- (NSArray *)getCalendarItemArrayWithDate:(NSDate *)date section:(NSInteger)section
{
NSMutableArray *resultArray = [[NSMutableArray alloc]init];
NSInteger tatalDay = [self numberOfDaysInCurrentMonth:date]; // 本月多少天
NSInteger firstDay = [self startDayOfWeek:date]; // 本月第一天是周几
// 0 星期日 1 星期一 6星期六
NSDateComponents *components = [self dateToComponents:date];
// 判断日历有多少列
// 一共多少天 加 第一天是周几就可以算出本月cell的数量
NSInteger tempDay = tatalDay + (firstDay - 1);
NSInteger column = 0;
if(tempDay % 7 == 0)
{
column = tempDay / 7;
}else{
column = tempDay / 7 + 1;
}
NSInteger i = 0;
NSInteger j = 0;
components.day = 0;
for(i = 0;i < column;i++)
{
for(j = 0;j < 7;j++)
{
if(i == 0 && j < firstDay - 1) // 本月第一天前的数据
{
MSSCalendarModel *calendarItem = [[MSSCalendarModel alloc]init];
calendarItem.year = 0;
calendarItem.month = 0;
calendarItem.day = 0;
calendarItem.chineseCalendar = @"";
calendarItem.holiday = @"";
calendarItem.week = -1;
calendarItem.dateInterval = -1;
[resultArray addObject:calendarItem];
continue;
}
components.day += 1;
if(components.day == tatalDay + 1) // 本月数据循环结束
{
i = column;// 结束外层循环
break;
}
MSSCalendarModel *calendarItem = [[MSSCalendarModel alloc]init];
calendarItem.year = components.year;
calendarItem.month = components.month;
calendarItem.day = components.day;
calendarItem.week = j;
NSDate *date = [self componentsToDate:components];
// 时间戳
calendarItem.dateInterval = [self dateToInterval:date];
if(_startDate == calendarItem.dateInterval)
{
_startIndexPath = [NSIndexPath indexPathForRow:0 inSection:section];
}
[self setChineseCalendarAndHolidayWithDate:components date:date calendarItem:calendarItem];
[resultArray addObject:calendarItem];
}
}
return resultArray;
}
价格日历这块,无非就是处理数据的时候加上了priceArray
@[ @{@"date":@"2018-09-08",@"price":@"238"}]
- (NSArray *)getJYCCalendarDataSoruceWithLimitMonth:(NSInteger)limitMonth type:(MSSCalendarViewControllerType)type calendarType:(MSSCalendarWithUserType)calendarType priceArray:(NSArray *_Nonnull)priceArray{
NSMutableArray *resultArray = [[NSMutableArray alloc]init];
NSMutableArray *priceMuArr = [NSMutableArray arrayWithArray:priceArray];
NSDateComponents *components = [self dateToComponents:_todayDate];
components.day = 1;
if(type == MSSCalendarViewControllerNextType)
{
components.month -= 1;
}
else if(type == MSSCalendarViewControllerLastType)
{
components.month -= limitMonth;
}
else
{
components.month -= (limitMonth + 1) / 2;
}
NSInteger i = 0;
for(i = 0;i < limitMonth;i++)
{
components.month++;
MSSCalendarHeaderModel *headerItem = [[MSSCalendarHeaderModel alloc]init];
NSDate *date = [self componentsToDate:components];
[_dateFormatter setDateFormat: @"yyyy年MM月"];
NSString *dateString = [_dateFormatter stringFromDate:date];
headerItem.headerText = dateString;
// 价格
NSString *MMyue = [dateString substringWithRange:NSMakeRange(5, 2)];
NSMutableArray *priArr = [NSMutableArray array];
for (NSDictionary *dic in priceMuArr) { // 从数据中选中当月的数据
NSString *da = [dic objectForKey:@"date"];
if (da.length > 7) {
NSString *mm = [da substringWithRange:NSMakeRange(5, 2)];
if (MMyue == mm) {
[priArr addObject:dic];
}
}
}
[priceMuArr removeObjectsInArray:priArr]; // 移除选中月份的数据
headerItem.calendarItemArray = [self getCalendarItemArrayWithDate:date section:i calendarType:calendarType withPriceArray:priArr];
[resultArray addObject:headerItem];
if (calendarType == MSSCalendarSecnicType || calendarType == MSSCalendarAplaceType || calendarType == MSSCalendarActivityType) {
if (priceMuArr.count <= 0) { // 如果价格数据数组为空时,不在展示以后的日历
break;
}
}
}
return resultArray;
}
找到第一天数据的具体时间,然后依次把数组中的数据赋值给第一天后的每一天(必须保证时间日历的连续性)
NSInteger priceTime = 0;
if (priceArray.count > 0) {
NSDictionary *dic = priceArray[0];
NSString *ti = [dic objectForKey:@"date"];
if (ti.length > 0) {
priceTime = [self dateToInterval:[self dateFromString:ti]];
}
}
// 时间戳
NSInteger dateInterVal = [self dateToInterval:date];
calendarItem.dateInterval = dateInterVal;
if (priceTime == dateInterVal) {
indexB = 0;
}
if (indexB < priceArray.count) {
NSDictionary *dic = priceArray[indexB];
// if (calendarType == MSSCalendarSecnicType) {
// calendarItem.price = [dic objectForKey:@"salePrice"];
// }else if (calendarType == MSSCalendarAplaceType){
// calendarItem.userPrice = [dic objectForKey:@"userprice"];
// calendarItem.price = [dic objectForKey:@"webprice"];
// }
calendarItem.price = [dic objectForKey:@"price"];
calendarItem.userInteractionEnabled = YES;
}
indexB++;
基地日历:选择一个开始时间后,后台刷新日历数据,把最小时间以前和最大时间以后的数据全部设置为不可选 userInteractionEnabled = NO;
- (NSArray *)getCalendarDataSoruceWithMinNum:(NSInteger )minNum MaxNum:(NSInteger )maxNum startDate:(NSInteger )startDate endDate:(NSInteger )endDate andDataArray:(NSArray *)dataArray{
NSMutableArray *daArr = [NSMutableArray array];
[daArr addObjectsFromArray:dataArray];
if (startDate > 0) {
for (int i = 0; i < dataArray.count; i++) {
MSSCalendarHeaderModel *headerItem = daArr[i];
for (int j = 0; j < headerItem.calendarItemArray.count; j++) {
MSSCalendarModel *model = headerItem.calendarItemArray[j];
if (model.dateInterval == startDate) {
}
if(model.dateInterval >= startDate + minNum*24*3600 && model.dateInterval <= startDate + maxNum*24*3600){
model.middleSelect = YES;
model.userInteractionEnabled = YES;
}else{
model.userInteractionEnabled = NO;
}
}
}
}
if (endDate > 0 || startDate == 0) {
for (int i = 0; i < dataArray.count; i++) {
MSSCalendarHeaderModel *headerItem = daArr[i];
for (int j = 0; j < headerItem.calendarItemArray.count; j++) {
MSSCalendarModel *model = headerItem.calendarItemArray[j];
if ([model.price floatValue] > 0) {
model.userInteractionEnabled = YES;
model.middleSelect = NO;
}
}
}
}
return daArr;
}
详见代码,
代码参考了一位大神,自己也封装了业务需求。
GitHub项目地址
网友评论