美文网首页iOS接下来要研究的知识点
iOS开发类携程日历,价格日历,单选,多选,可选不可选

iOS开发类携程日历,价格日历,单选,多选,可选不可选

作者: 何年何月 | 来源:发表于2018-09-04 16:49 被阅读101次

    之前开发也遇到过酒店,火车票日历,我用了一款第三方软件,前期还行,随着后期功能(业务)增多,就不好使了,特别是那个循环架构,年 月 日这种的,修改起来特别麻烦。
    新增业务例如:
    1、价格日历,景点价格日历,机票价格日历
    2、基地日历,我们基地价格分批次的 1-8天 110元/天,9-20天100 ,21-30天90,这就要求选择开始日期后,重新刷新数据,只能选择天数区域内的时间。
    3、活动日历,活动不是每天搞,隔三差五的,一句话就是可点不可点,传日期输入,处理后展示出来。

    先上图。 日历.gif
    #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项目地址

    相关文章

      网友评论

        本文标题:iOS开发类携程日历,价格日历,单选,多选,可选不可选

        本文链接:https://www.haomeiwen.com/subject/glggwftx.html