iOS仿酒店入住离店日历(Calendar)选择

来源:互联网 发布:淘宝上日本直邮几天 编辑:程序博客网 时间:2024/05/02 15:44

最近做一个项目,有个日历选择功能,就仿美团做了一个,将思路、代码分享一下。先上图片,直观体验一下
Demo下载地址:
https://github.com/TechAlleyBoy/CalendarDemo
http://download.csdn.net/download/techalleyboy/9840841
这里写图片描述
这里写图片描述
一:数据源的准备工作,各种日期的计算工作

1:根据NSDate获得年月日,及星期几

#pragma mark - 获取年,月,日,星期 //注:日历获取在9.x之后的系统使用currentCalendar会出异常。在8.0之后使用系统新API。-(NSInteger )getDataFromDate:(NSDate *)date type:(NSString * )type{    NSCalendar *calendar = nil;    if ([NSCalendar respondsToSelector:@selector(calendarWithIdentifier:)]) {        calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];    }else{        calendar = [NSCalendar currentCalendar];    }    NSDateComponents *components = [calendar components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay |NSCalendarUnitWeekday) fromDate:date];    if ([type isEqualToString:@"year"]) {        return components.year;    }else if ([type isEqualToString:@"month"]) {        return components.month;    }else if ([type isEqualToString:@"day"]) {        return components.day;    }else if ([type isEqualToString:@"week"]) {        return components.weekday;    }else{        return 0;    }}

2:根据NSDate获得当月一共几天

#pragma mark -- 获取当前月共有多少天- (NSInteger)totaldaysInMonth:(NSDate *)date{    NSRange daysInLastMonth = [[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:date];    return daysInLastMonth.length;}

3:时间字符串转时间

#pragma mark - 时间字符串转时间-(NSDate *)dateWithYear:(NSInteger )year month:(NSInteger )month day:(NSInteger )day{    NSDateFormatter *formatter = [[NSDateFormatter alloc]init];    [formatter setDateFormat:@"yyyyMMdd"];    return [formatter dateFromString:[NSString stringWithFormat:@"%ld%02ld%02ld",year,month,day]];}

二:模型Model的建立
注:模型里面套模型 月的模型(MonthModel) 中 有一个NSArray

////  MonthModel.h//  BJTResearch////  Created by yunlong on 17/5/12.//  Copyright © 2017年 yunlong. All rights reserved.//#import <Foundation/Foundation.h>#import <UIKit/UIKit.h>typedef enum : NSUInteger {    DayModelStateNormal = 0,    DayModelStateStart,    DayModelStateEnd,    DayModelStateSelected,} DayModelState;typedef enum : NSUInteger {    Sunday = 1,    Monday,    Tuesday,    Wednesday,    Thursday,    Friday,    Saturday,} DayModelOfTheWeek;@interface DayModel : NSObject/** * 年 */@property(nonatomic,assign)NSInteger year;/** * 月 */@property(nonatomic,assign)NSInteger month;/** * 日 */@property(nonatomic,assign)NSInteger day;/** * 日期 */@property(nonatomic,strong)NSDate *dayDate;/** * 星期 */@property(nonatomic,assign)DayModelOfTheWeek dayOfTheWeek;/** * 日期的状态 */@property(nonatomic,assign)DayModelState state;/** * 日期是不是今天 */@property(nonatomic,assign)BOOL isToday;@end@interface MonthModel : NSObject/** * 年 */@property(nonatomic,assign)NSInteger year;/** * 月 */@property(nonatomic,assign)NSInteger month;/** * 一个月中UICollectionViewCell的个数 */@property(nonatomic,assign)NSInteger cellNum;/** * 月UITableViewCell的高度 */@property(nonatomic,assign)CGFloat cellHight;/** * UICollectionViewCell开始的位置 */@property(nonatomic,assign)NSInteger cellStartNum;/** * 月DayModel数组 */@property(nonatomic,strong)NSArray<DayModel *> * days;@end

2:.m文件

#import "MonthModel.h"@implementation DayModel@end@implementation MonthModel@end

三:数据源建立
几点说明
1:采用数据源懒加载,用到时加载。
2:这个demo一共加载了13个月:for (int i = 0; i<13; i++)
3:i == 0特殊处理额原因,因为第一个月的起始日期是当前日期,不是1号。
4:NSInteger oneLineCoune =( 7 - m.dayOfTheWeek + 2 ) % 7;这是计算第一行中cell的个数,components.weekday中,weekday=1是周日,周一是2。

/////////////////////////////////////数据处理///////////////////////////////////////////#pragma mark - 懒加载数据源-(NSMutableArray *)dataArray{    if (!_dataArray) {        _dataArray = [NSMutableArray array];        NSDate *nowdate = [NSDate date];        NSInteger toYear = [self getDataFromDate:nowdate type:@"year"];        NSInteger toMonth = [self getDataFromDate:nowdate type:@"month"];        for (int i = 0; i<13; i++) {            if (i == 0) {                MonthModel  * monthModel = [[MonthModel alloc] init];                monthModel.year = toYear;                monthModel.month = toMonth;                NSMutableArray *days = [NSMutableArray array ];                NSInteger starNum = [self getDataFromDate :nowdate type:@"day"];                for (NSInteger i = starNum ; i <=[self totaldaysInMonth:nowdate]; i++) {                    DayModel *dayModel = [[DayModel alloc]init];                    dayModel.dayDate = [self dateWithYear:monthModel.year month:monthModel.month day:i];                    dayModel.day = i;                    dayModel.month = monthModel.month;                    dayModel.year = monthModel.year;                    dayModel.dayOfTheWeek = [self getDataFromDate:dayModel.dayDate type:@"week"];                    dayModel.isToday = i==starNum;                    dayModel.state = DayModelStateNormal;                    [days addObject:dayModel];                }                monthModel.days = days;                DayModel *m = days.firstObject;                NSInteger lineCount = 1;                NSInteger oneLineCoune =( 7 - m.dayOfTheWeek + 2 ) % 7;                if (oneLineCoune == 0) {                    oneLineCoune = 7;                }                NSInteger count = days.count - oneLineCoune;                if (count%7==0) {                    lineCount = lineCount + count/7 ;                }else{                    lineCount = lineCount + count/7 + 1 ;                }                monthModel.cellNum = lineCount * 7;                monthModel.cellStartNum = 7 - oneLineCoune ;                monthModel.cellHight = 60 + 60 * lineCount + 2 * (lineCount + 1);                [_dataArray addObject:monthModel];                toMonth++;            }else{                if (toMonth == 13) {                    toMonth = 1;                    toYear += 1;                }                NSDate *toDate = [self dateWithYear:toYear month:toMonth day:1];                MonthModel  * monthModel = [[MonthModel alloc] init];                monthModel.year = [self getDataFromDate:toDate type:@"year"];                monthModel.month = [self getDataFromDate:toDate type:@"month"];                NSMutableArray *days = [NSMutableArray array ];                for (NSInteger i = 1 ; i <=[self totaldaysInMonth:toDate]; i++) {                    DayModel *dayModel = [[DayModel alloc]init];                    dayModel.dayDate = [self dateWithYear:monthModel.year month:monthModel.month day:i];                    dayModel.day = i;                    dayModel.month = monthModel.month;                    dayModel.year = monthModel.year;                    dayModel.dayOfTheWeek = [self getDataFromDate:dayModel.dayDate type:@"week"];                    dayModel.isToday = NO;                    dayModel.state = DayModelStateNormal;                    [days addObject:dayModel];                }                monthModel.days = days;                DayModel *m = days.firstObject;                NSInteger lineCount = 1;                NSInteger oneLineCoune =( 7 - m.dayOfTheWeek + 2 ) % 7;                if (oneLineCoune == 0) {                    oneLineCoune = 7;                }                NSInteger count = days.count - oneLineCoune;                if (count%7==0) {                    lineCount = lineCount + count/7 ;                }else{                    lineCount = lineCount + count/7 + 1 ;                }                monthModel.cellNum = lineCount * 7;                monthModel.cellStartNum = 7 - oneLineCoune ;                monthModel.cellHight = 60 + 60 * lineCount + 2 * (lineCount + 1);                [_dataArray addObject:monthModel];                toMonth++;            }        }    }    return _dataArray;}

四:视图创建
1:星期视图是个单独的view,详见代码
2:整体是tableview中嵌套collectionview,每个月是一个tableviewcell,每天是一个collectionviewcell。如下图:
这里写图片描述

3:UICollectionViewCell里面还有节假日及公历的计算,详见代码

四:特殊注意的几个地方
1:选择时间分为几种情况
1):没有入住,没有离店
2):有入住,没离店
3):有入住,有离店

__weak typeof(self) weakSelf = self;    cell.selectedDay = ^(DayModel *returnDaymodel){        BOOL isHaveStart = NO;        BOOL isHaveEnd = NO;        BOOL isHaveSelected = NO;        NSDate *startDate ;        NSDate *endDate ;        DayModel *starModel;        DayModel *endModel;        for (MonthModel *Mo in self.dataArray) {            for (DayModel *mo in Mo.days) {                if (mo.state == DayModelStateStart) {                    isHaveStart = YES;                    startDate = mo.dayDate;                    starModel = mo;                }else if (mo.state == DayModelStateSelected) {                    isHaveSelected = YES;                }else if (mo.state == DayModelStateEnd) {                    isHaveEnd = YES;                    endDate = mo.dayDate;                    endModel = mo;                    break;                }            }        }        if ((!isHaveStart && !isHaveEnd && !isHaveSelected )|| (!isHaveStart && !isHaveEnd) ) {            //没有设置开始结束            returnDaymodel.state = DayModelStateStart;        }else if ((isHaveEnd && isHaveStart)){            //有开始有结束            for (MonthModel *Mo in weakSelf.dataArray) {                for (DayModel *mo in Mo.days) {                    mo.state = DayModelStateNormal;                }            }            returnDaymodel.state = DayModelStateStart;        }else if(isHaveStart && !isHaveEnd){            //有开始没有结束            NSInteger ci = [self compareDate:returnDaymodel.dayDate withDate:startDate];            switch (ci) {                case 1://startDate > currentSelectDate                    starModel.state = DayModelStateNormal;                    returnDaymodel.state = DayModelStateStart;                    break;                case -1:                    returnDaymodel.state = DayModelStateEnd;                    for (MonthModel *Mo in weakSelf.dataArray) {                        for (DayModel *mo in Mo.days) {                            NSInteger ci1 = [weakSelf compareDate:mo.dayDate withDate:startDate];                            NSInteger ci2 = [weakSelf compareDate:mo.dayDate withDate:returnDaymodel.dayDate];                            if (ci1 == -1 && ci2 == 1 ) {                                mo.state = DayModelStateSelected;                            }                        }                    }                    break;                case 0:                    returnDaymodel.state = DayModelStateNormal;                    break;                default:                    break;            }        }        [weakSelf.tableView reloadData];    };

2:选择入住和离店时间,及其总时长时,会用到下面两个方法

#pragma mark-日期比较-(NSInteger )compareDate:(NSDate *)date01 withDate:(NSDate *)date02{    NSInteger ci;    NSComparisonResult result = [date01 compare:date02];    switch (result)    {            //date02比date01大        case NSOrderedAscending: ci=1; break;            //date02比date01小        case NSOrderedDescending: ci=-1; break;            //date02=date01        case NSOrderedSame: ci=0; break;        default: NSLog(@"erorr dates %@, %@", date02, date01); break;    }    return ci;}#pragma mark -  计算两个日期之间的天数- (NSInteger) calcDaysFromBegin:(NSDate *)beginDate end:(NSDate *)endDate{    //创建日期格式化对象    NSDateFormatter *dateFormatter=[[NSDateFormatter alloc] init];    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm"];    //取两个日期对象的时间间隔:    //这里的NSTimeInterval 并不是对象,是基本型,其实是double类型,是由c定义的:typedef double NSTimeInterval;    NSTimeInterval time=[endDate timeIntervalSinceDate:beginDate];    int days=((int)time)/(3600*24);    //int hours=((int)time)%(3600*24)/3600;    //NSString *dateContent=[[NSString alloc] initWithFormat:@"%i天%i小时",days,hours];    return days;}
1 0
原创粉丝点击