之前開發(fā)也遇到過酒店,火車票日歷,我用了一款第三方軟件,前期還行,隨著后期功能(業(yè)務(wù))增多,就不好使了,特別是那個(gè)循環(huán)架構(gòu),年 月 日這種的,修改起來特別麻煩。
新增業(yè)務(wù)例如:
1、價(jià)格日歷,景點(diǎn)價(jià)格日歷,機(jī)票價(jià)格日歷
2、基地日歷,我們基地價(jià)格分批次的 1-8天 110元/天,9-20天100 ,21-30天90,這就要求選擇開始日期后,重新刷新數(shù)據(jù),只能選擇天數(shù)區(qū)域內(nèi)的時(shí)間。
3、活動(dòng)日歷,活動(dòng)不是每天搞,隔三差五的,一句話就是可點(diǎn)不可點(diǎn),傳日期輸入,處理后展示出來。

#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])
/*定義屬性*/
// 選擇點(diǎn)擊顏色
#define SelectedColor [UIColor cyanColor]
// 被選中間顏色
#define SelMiddleColor [UIColor greenColor]
// DateLabel默認(rèn)文字顏色
#define MSS_TextColor [UIColor blackColor]
// DateLabel選中時(shí)的背景色
#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選中結(jié)束文字
#define MSS_SelectEndText @"結(jié)束"
// 節(jié)日顏色
#define MSS_HolidayTextColor [UIColor purpleColor]
// 周末顏色
#define MSS_WeekEndTextColor [UIColor redColor]
// 不可點(diǎn)擊文字顏色
#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,// 只顯示當(dāng)前月之前
MSSCalendarViewControllerMiddleType,// 前后各顯示一半
MSSCalendarViewControllerNextType// 只顯示當(dāng)前月之后
};
typedef NS_ENUM(NSInteger, MSSCalendarWithUserType)
{
MSSCalendarHotelType = 0, // 酒店 入住 --- 離店
MSSCalendarTrainType, // 火車票,飛機(jī)票,單選無價(jià)格
MSSCalendarAplaceType, // 基地 價(jià)格
MSSCalendarSecnicType, // 景點(diǎn) 價(jià)格
MSSCalendarPlaneType, // 機(jī)票
MSSCalendarActivityType // 活動(dòng),線路
};
可以自定義以上屬性,什么顏色,類型什么的。
核心思路就在這塊,簡(jiǎn)單明了,傳的有一個(gè)參數(shù)limitMonth,顯示幾個(gè)月的數(shù)據(jù),MSSCalendarViewControllerNextType就是今天以后, components.month -= 1;獲取當(dāng)前月份減一,不要問為什么減一,打隔斷點(diǎn)看看就知道了,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就是當(dāng)月數(shù)據(jù)頁面的位置
[resultArray addObject:headerItem];
}
return resultArray;
}
一共limitMonth個(gè)月,從第一個(gè)月開始排序,整理數(shù)組。下面是每一個(gè)單獨(dú)月的日期數(shù)據(jù)
// 得到每一天的數(shù)據(jù)源
- (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的數(shù)量
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) // 本月第一天前的數(shù)據(jù)
{
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) // 本月數(shù)據(jù)循環(huán)結(jié)束
{
i = column;// 結(jié)束外層循環(huán)
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];
// 時(shí)間戳
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;
}
價(jià)格日歷這塊,無非就是處理數(shù)據(jù)的時(shí)候加上了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;
// 價(jià)格
NSString *MMyue = [dateString substringWithRange:NSMakeRange(5, 2)];
NSMutableArray *priArr = [NSMutableArray array];
for (NSDictionary *dic in priceMuArr) { // 從數(shù)據(jù)中選中當(dāng)月的數(shù)據(jù)
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]; // 移除選中月份的數(shù)據(jù)
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) { // 如果價(jià)格數(shù)據(jù)數(shù)組為空時(shí),不在展示以后的日歷
break;
}
}
}
return resultArray;
}
找到第一天數(shù)據(jù)的具體時(shí)間,然后依次把數(shù)組中的數(shù)據(jù)賦值給第一天后的每一天(必須保證時(shí)間日歷的連續(xù)性)
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]];
}
}
// 時(shí)間戳
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++;
基地日歷:選擇一個(gè)開始時(shí)間后,后臺(tái)刷新日歷數(shù)據(jù),把最小時(shí)間以前和最大時(shí)間以后的數(shù)據(jù)全部設(shè)置為不可選 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;
}
詳見代碼,
代碼參考了一位大神,自己也封裝了業(yè)務(wù)需求。
GitHub項(xiàng)目地址