├── Preview ├── preview-2@2x.jpg ├── preview-3@2x.jpg ├── preview-4@2x.jpg └── preview-5@2x.jpg ├── Class ├── Other │ ├── CalendarRow.png │ ├── CalendarRow@2x.png │ ├── CalendarRowBottom.png │ ├── CalendarDisableDate.png │ ├── CalendarNormalDate.png │ ├── CalendarTodaysDate.png │ ├── CalendarPreviousMonth.png │ ├── CalendarRowBottom@2x.png │ ├── CalendarSelectedDate.png │ ├── CalendarTodaysDate@2x.png │ ├── CalendarPreviousMonth@2x.png │ └── CalendarSelectedDate@2x.png ├── Model │ ├── TicketModel.m │ ├── TicketModel.h │ ├── RMCalendarModel.m │ └── RMCalendarModel.h ├── View │ ├── RMCalendarCollectionViewLayout.h │ ├── RMCalendarMonthHeaderView.h │ ├── RMCollectionCell.h │ ├── RMCalendarMonthHeaderView.m │ ├── RMCalendarCollectionViewLayout.m │ └── RMCollectionCell.m ├── Category │ ├── UIView+CustomFrame.h │ ├── NSDate+RMCalendarLogic.h │ ├── UIView+CustomFrame.m │ └── NSDate+RMCalendarLogic.m ├── Logic │ ├── RMCalendarLogic.h │ └── RMCalendarLogic.m └── Controller │ ├── RMCalendarController.h │ └── RMCalendarController.m ├── RMCalendar ├── Default-568h@2x.png ├── ViewController.h ├── MJExtension │ ├── MJFoundation.h │ ├── MJExtension.h │ ├── NSString+MJExtension.h │ ├── MJConst.m │ ├── MJType.h │ ├── NSObject+MJCoding.h │ ├── MJFoundation.m │ ├── MJProperty.h │ ├── NSObject+MJCoding.m │ ├── MJType.m │ ├── MJConst.h │ ├── NSString+MJExtension.m │ ├── MJProperty.m │ ├── NSObject+MJProperty.h │ ├── NSObject+MJKeyValue.h │ ├── NSObject+MJProperty.m │ └── NSObject+MJKeyValue.m ├── AppDelegate.h ├── main.m ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── AppDelegate.m ├── ViewController.m └── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── RMCalendar.xcodeproj ├── xcuserdata │ ├── chd.xcuserdatad │ │ ├── xcdebugger │ │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ │ ├── xcschememanagement.plist │ │ │ └── RMCalendar.xcscheme │ └── chihaodong.xcuserdatad │ │ ├── xcschemes │ │ └── xcschememanagement.plist │ │ └── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcuserdata │ │ ├── chd.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ │ └── chihaodong.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcshareddata │ │ └── RMCalendar.xccheckout └── project.pbxproj ├── RMCalendarTests ├── Info.plist └── RMCalendarTests.m └── README.md /Preview/preview-2@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chihaodong/RMCalendar/HEAD/Preview/preview-2@2x.jpg -------------------------------------------------------------------------------- /Preview/preview-3@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chihaodong/RMCalendar/HEAD/Preview/preview-3@2x.jpg -------------------------------------------------------------------------------- /Preview/preview-4@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chihaodong/RMCalendar/HEAD/Preview/preview-4@2x.jpg -------------------------------------------------------------------------------- /Preview/preview-5@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chihaodong/RMCalendar/HEAD/Preview/preview-5@2x.jpg -------------------------------------------------------------------------------- /Class/Other/CalendarRow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chihaodong/RMCalendar/HEAD/Class/Other/CalendarRow.png -------------------------------------------------------------------------------- /Class/Other/CalendarRow@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chihaodong/RMCalendar/HEAD/Class/Other/CalendarRow@2x.png -------------------------------------------------------------------------------- /RMCalendar/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chihaodong/RMCalendar/HEAD/RMCalendar/Default-568h@2x.png -------------------------------------------------------------------------------- /Class/Other/CalendarRowBottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chihaodong/RMCalendar/HEAD/Class/Other/CalendarRowBottom.png -------------------------------------------------------------------------------- /Class/Other/CalendarDisableDate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chihaodong/RMCalendar/HEAD/Class/Other/CalendarDisableDate.png -------------------------------------------------------------------------------- /Class/Other/CalendarNormalDate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chihaodong/RMCalendar/HEAD/Class/Other/CalendarNormalDate.png -------------------------------------------------------------------------------- /Class/Other/CalendarTodaysDate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chihaodong/RMCalendar/HEAD/Class/Other/CalendarTodaysDate.png -------------------------------------------------------------------------------- /Class/Other/CalendarPreviousMonth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chihaodong/RMCalendar/HEAD/Class/Other/CalendarPreviousMonth.png -------------------------------------------------------------------------------- /Class/Other/CalendarRowBottom@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chihaodong/RMCalendar/HEAD/Class/Other/CalendarRowBottom@2x.png -------------------------------------------------------------------------------- /Class/Other/CalendarSelectedDate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chihaodong/RMCalendar/HEAD/Class/Other/CalendarSelectedDate.png -------------------------------------------------------------------------------- /Class/Other/CalendarTodaysDate@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chihaodong/RMCalendar/HEAD/Class/Other/CalendarTodaysDate@2x.png -------------------------------------------------------------------------------- /Class/Other/CalendarPreviousMonth@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chihaodong/RMCalendar/HEAD/Class/Other/CalendarPreviousMonth@2x.png -------------------------------------------------------------------------------- /Class/Other/CalendarSelectedDate@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chihaodong/RMCalendar/HEAD/Class/Other/CalendarSelectedDate@2x.png -------------------------------------------------------------------------------- /RMCalendar.xcodeproj/xcuserdata/chd.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /RMCalendar.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /RMCalendar.xcodeproj/project.xcworkspace/xcuserdata/chd.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chihaodong/RMCalendar/HEAD/RMCalendar.xcodeproj/project.xcworkspace/xcuserdata/chd.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /RMCalendar.xcodeproj/project.xcworkspace/xcuserdata/chihaodong.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chihaodong/RMCalendar/HEAD/RMCalendar.xcodeproj/project.xcworkspace/xcuserdata/chihaodong.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Class/Model/TicketModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // TicketModel.m 3 | // RMCalendar 4 | // 5 | // Created by 迟浩东 on 15/7/6. 6 | // Copyright (c) 2015年 迟浩东. All rights reserved. 7 | // 8 | 9 | #import "TicketModel.h" 10 | 11 | @implementation TicketModel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /RMCalendar/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // RMCalendar 4 | // 5 | // Created by 迟浩东 on 15/7/1. 6 | // Copyright (c) 2015年 迟浩东. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /RMCalendar/MJExtension/MJFoundation.h: -------------------------------------------------------------------------------- 1 | // 2 | // MJFoundation.h 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 14/7/16. 6 | // Copyright (c) 2014年 小码哥. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MJFoundation : NSObject 12 | + (BOOL)isClassFromFoundation:(Class)c; 13 | @end 14 | -------------------------------------------------------------------------------- /Class/View/RMCalendarCollectionViewLayout.h: -------------------------------------------------------------------------------- 1 | // 2 | // RMCalendarCollectionViewLayout.h 3 | // RMCalendar 4 | // 5 | // Created by 迟浩东 on 15/7/15. 6 | // Copyright © 2015年 迟浩东(http://www.ruanman.net). All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RMCalendarCollectionViewLayout : UICollectionViewFlowLayout 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /RMCalendar/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // RMCalendar 4 | // 5 | // Created by 迟浩东 on 15/7/1. 6 | // Copyright (c) 2015年 迟浩东. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /Class/View/RMCalendarMonthHeaderView.h: -------------------------------------------------------------------------------- 1 | // 2 | // RMCalendarMonthHeaderView.h 3 | // RMCalendar 4 | // 5 | // Created by 迟浩东 on 15/7/15. 6 | // Copyright © 2015年 迟浩东(http://www.ruanman.net). All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RMCalendarMonthHeaderView : UICollectionReusableView 12 | 13 | @property (weak, nonatomic) UILabel *masterLabel; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Class/View/RMCollectionCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // RMCollectionCell.h 3 | // RMCalendar 4 | // 5 | // Created by 迟浩东 on 15/7/15. 6 | // Copyright © 2015年 迟浩东(http://www.ruanman.net). All rights reserved. 7 | // 8 | 9 | #import 10 | @class RMCalendarModel; 11 | 12 | @interface RMCollectionCell : UICollectionViewCell 13 | 14 | @property(nonatomic, strong) RMCalendarModel *model; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /RMCalendar/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // RMCalendar 4 | // 5 | // Created by 迟浩东 on 15/7/1. 6 | // Copyright (c) 2015年 迟浩东. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /RMCalendar.xcodeproj/xcuserdata/chihaodong.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | RMCalendar.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /RMCalendar/MJExtension/MJExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // MJExtension.h 3 | // MJExtension 4 | // 5 | // Created by mj on 14-1-15. 6 | // Copyright (c) 2014年 小码哥. All rights reserved. 7 | // 代码地址:https://github.com/CoderMJLee/MJExtension 8 | // 代码地址:http://code4app.com/ios/%E5%AD%97%E5%85%B8-JSON-%E4%B8%8E%E6%A8%A1%E5%9E%8B%E7%9A%84%E8%BD%AC%E6%8D%A2/5339992a933bf062608b4c57 9 | 10 | #import "NSObject+MJCoding.h" 11 | #import "NSObject+MJProperty.h" 12 | #import "NSObject+MJKeyValue.h" 13 | #import "NSString+MJExtension.h" 14 | -------------------------------------------------------------------------------- /RMCalendar/MJExtension/NSString+MJExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+MJExtension.h 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 15/6/7. 6 | // Copyright (c) 2015年 小码哥. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (MJExtension) 12 | /** 13 | * 驼峰转下划线(loveYou -> love_you) 14 | */ 15 | - (NSString *)underlineFromCamel; 16 | /** 17 | * 下划线转驼峰(love_you -> loveYou) 18 | */ 19 | - (NSString *)camelFromUnderline; 20 | /** 21 | * 首字母变大写 22 | */ 23 | - (NSString *)firstCharUpper; 24 | /** 25 | * 首字母变小写 26 | */ 27 | - (NSString *)firstCharLower; 28 | @end 29 | -------------------------------------------------------------------------------- /Class/Category/UIView+CustomFrame.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+CustomFrame.h 3 | // RMCalendar 4 | // 5 | // Created by 迟浩东 on 15/4/30. 6 | // Copyright (c) 2015年 CHD. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIView (CustomFrame) 12 | 13 | @property (nonatomic, assign) CGFloat x; 14 | @property (nonatomic, assign) CGFloat y; 15 | @property (nonatomic, assign) CGFloat centerX; 16 | @property (nonatomic, assign) CGFloat centerY; 17 | @property (nonatomic, assign) CGFloat width; 18 | @property (nonatomic, assign) CGFloat height; 19 | @property (nonatomic, assign) CGSize size; 20 | @property (nonatomic, assign) CGPoint origin; 21 | @end 22 | -------------------------------------------------------------------------------- /Class/Model/TicketModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // TicketModel.h 3 | // RMCalendar 4 | // 5 | // Created by 迟浩东 on 15/7/6. 6 | // Copyright (c) 2015年 迟浩东. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TicketModel : NSObject 12 | /** 13 | * 年 14 | */ 15 | @property (nonatomic, assign) NSInteger year; 16 | /** 17 | * 月 18 | */ 19 | @property (nonatomic, assign) NSInteger month; 20 | /** 21 | * 日 22 | */ 23 | @property (nonatomic, assign) NSInteger day; 24 | /** 25 | * 剩余数量 26 | */ 27 | @property (nonatomic, assign) NSInteger ticketCount; 28 | /** 29 | * 单价 30 | */ 31 | @property (nonatomic, assign) float ticketPrice; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /RMCalendar.xcodeproj/xcuserdata/chd.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | RMCalendar.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | EE4A4FEE1B43E881004B6590 16 | 17 | primary 18 | 19 | 20 | EE4A50071B43E881004B6590 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /RMCalendar/MJExtension/MJConst.m: -------------------------------------------------------------------------------- 1 | #ifndef __MJConst__M__ 2 | #define __MJConst__M__ 3 | 4 | #import 5 | 6 | /** 7 | * 成员变量类型(属性类型) 8 | */ 9 | NSString *const MJTypeInt = @"i"; 10 | NSString *const MJTypeFloat = @"f"; 11 | NSString *const MJTypeDouble = @"d"; 12 | NSString *const MJTypeLong = @"q"; 13 | NSString *const MJTypeLongLong = @"q"; 14 | NSString *const MJTypeChar = @"c"; 15 | NSString *const MJTypeBOOL = @"c"; 16 | NSString *const MJTypePointer = @"*"; 17 | 18 | NSString *const MJTypeIvar = @"^{objc_ivar=}"; 19 | NSString *const MJTypeMethod = @"^{objc_method=}"; 20 | NSString *const MJTypeBlock = @"@?"; 21 | NSString *const MJTypeClass = @"#"; 22 | NSString *const MJTypeSEL = @":"; 23 | NSString *const MJTypeId = @"@"; 24 | 25 | #endif -------------------------------------------------------------------------------- /RMCalendar/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /RMCalendarTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.ruanman.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /RMCalendar/MJExtension/MJType.h: -------------------------------------------------------------------------------- 1 | // 2 | // MJType.h 3 | // MJExtension 4 | // 5 | // Created by mj on 14-1-15. 6 | // Copyright (c) 2014年 小码哥. All rights reserved. 7 | // 包装一种类型 8 | 9 | #import 10 | /** 11 | * 包装一种类型 12 | */ 13 | @interface MJType : NSObject 14 | /** 类型标识符 */ 15 | @property (nonatomic, copy) NSString *code; 16 | 17 | /** 是否为id类型 */ 18 | @property (nonatomic, readonly, getter=isIdType) BOOL idType; 19 | 20 | /** 是否为基本数字类型:int、float等 */ 21 | @property (nonatomic, readonly, getter=isNumberType) BOOL numberType; 22 | 23 | /** 对象类型(如果是基本数据类型,此值为nil) */ 24 | @property (nonatomic, readonly) Class typeClass; 25 | 26 | /** 类型是否来自于Foundation框架,比如NSString、NSArray */ 27 | @property (nonatomic, readonly, getter = isFromFoundation) BOOL fromFoundation; 28 | /** 类型是否不支持KVC */ 29 | @property (nonatomic, readonly, getter = isKVCDisabled) BOOL KVCDisabled; 30 | 31 | /** 32 | * 获得缓存的类型对象 33 | */ 34 | + (instancetype)cachedTypeWithCode:(NSString *)code; 35 | @end -------------------------------------------------------------------------------- /RMCalendar/MJExtension/NSObject+MJCoding.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+MJCoding.h 3 | // MJExtension 4 | // 5 | // Created by mj on 14-1-15. 6 | // Copyright (c) 2014年 小码哥. All rights reserved. 7 | // 8 | 9 | #import 10 | /** 11 | * Codeing协议 12 | */ 13 | @protocol MJCoding 14 | @optional 15 | /** 16 | * 这个数组中的属性名才会进行归档 17 | */ 18 | + (NSArray *)allowedCodingPropertyNames; 19 | /** 20 | * 这个数组中的属性名将会被忽略:不进行归档 21 | */ 22 | + (NSArray *)ignoredCodingPropertyNames; 23 | @end 24 | 25 | @interface NSObject (MJCoding) 26 | /** 27 | * 解码(从文件中解析对象) 28 | */ 29 | - (void)decode:(NSCoder *)decoder; 30 | /** 31 | * 编码(将对象写入文件中) 32 | */ 33 | - (void)encode:(NSCoder *)encoder; 34 | @end 35 | 36 | /** 37 | 归档的实现 38 | */ 39 | #define MJCodingImplementation \ 40 | - (id)initWithCoder:(NSCoder *)decoder \ 41 | { \ 42 | if (self = [super init]) { \ 43 | [self decode:decoder]; \ 44 | } \ 45 | return self; \ 46 | } \ 47 | \ 48 | - (void)encodeWithCoder:(NSCoder *)encoder \ 49 | { \ 50 | [self encode:encoder]; \ 51 | } -------------------------------------------------------------------------------- /RMCalendarTests/RMCalendarTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMCalendarTests.m 3 | // RMCalendarTests 4 | // 5 | // Created by 迟浩东 on 15/7/1. 6 | // Copyright (c) 2015年 迟浩东. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface RMCalendarTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation RMCalendarTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /Class/Category/NSDate+RMCalendarLogic.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate+RMCalendarLogic.h 3 | // RMCalendar 4 | // 5 | // Created by 迟浩东 on 15/7/15. 6 | // Copyright © 2015年 迟浩东(http://www.ruanman.net). All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSDate (RMCalendarLogic) 12 | 13 | - (NSUInteger)numberOfDaysInCurrentMonth; 14 | 15 | - (NSUInteger)numberOfWeeksInCurrentMonth; 16 | 17 | - (NSUInteger)weeklyOrdinality; 18 | 19 | - (NSDate *)firstDayOfCurrentMonth; 20 | 21 | - (NSDate *)lastDayOfCurrentMonth; 22 | 23 | - (NSDate *)dayInThePreviousMonth; 24 | 25 | - (NSDate *)dayInTheFollowingMonth; 26 | 27 | - (NSDate *)dayInTheFollowingMonth:(int)month;//获取当前日期之后的几个月 28 | 29 | - (NSDate *)dayInTheFollowingDay:(int)day;//获取当前日期之后的几个天 30 | 31 | - (NSDateComponents *)YMDComponents; 32 | 33 | - (NSDate *)dateFromString:(NSString *)dateString;//NSString转NSDate 34 | 35 | - (NSString *)stringFromDate:(NSDate *)date;//NSDate转NSString 36 | 37 | + (int)getDayNumbertoDay:(NSDate *)today beforDay:(NSDate *)beforday; 38 | 39 | -(int)getWeekIntValueWithDate; 40 | 41 | 42 | 43 | //判断日期是今天,明天,后天,周几 44 | -(NSString *)compareIfTodayWithDate; 45 | //通过数字返回星期几 46 | +(NSString *)getWeekStringFromInteger:(int)week; 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /RMCalendar/MJExtension/MJFoundation.m: -------------------------------------------------------------------------------- 1 | // 2 | // MJFoundation.m 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 14/7/16. 6 | // Copyright (c) 2014年 小码哥. All rights reserved. 7 | // 8 | 9 | #import "MJFoundation.h" 10 | #import "MJConst.h" 11 | #import 12 | 13 | static NSSet *_foundationClasses; 14 | 15 | @implementation MJFoundation 16 | 17 | + (void)load 18 | { 19 | _foundationClasses = [NSSet setWithObjects: 20 | [NSObject class], 21 | [NSURL class], 22 | [NSDate class], 23 | [NSNumber class], 24 | [NSDecimalNumber class], 25 | [NSData class], 26 | [NSMutableData class], 27 | [NSArray class], 28 | [NSMutableArray class], 29 | [NSDictionary class], 30 | [NSMutableDictionary class], 31 | [NSManagedObject class], 32 | [NSString class], 33 | [NSMutableString class], nil]; 34 | } 35 | 36 | + (BOOL)isClassFromFoundation:(Class)c 37 | { 38 | return [_foundationClasses containsObject:c]; 39 | } 40 | @end 41 | -------------------------------------------------------------------------------- /Class/Logic/RMCalendarLogic.h: -------------------------------------------------------------------------------- 1 | // 2 | // RMCalendarLogic.h 3 | // RMCalendar 4 | // 5 | // Created by 迟浩东 on 15/7/15. 6 | // Copyright © 2015年 迟浩东(http://www.ruanman.net). All rights reserved. 7 | // 8 | 9 | #import 10 | #import "RMCalendarModel.h" 11 | 12 | /** 13 | * 日历显示的月数 14 | */ 15 | typedef NS_ENUM(NSInteger, CalendarShowType){ 16 | /** 17 | * 只显示当月 18 | */ 19 | CalendarShowTypeSingle, 20 | /** 21 | * 显示多个月数 22 | */ 23 | CalendarShowTypeMultiple 24 | }; 25 | 26 | @interface RMCalendarLogic : NSObject 27 | 28 | -(NSMutableArray *)reloadCalendarView:(NSDate *)date selectDate:(NSDate *)selectDate needDays:(int)days showType:(CalendarShowType)type isEnable:(BOOL)isEnable priceModelArr:(NSArray *)arr isChineseCalendar:(BOOL)isChineseCalendar; 29 | 30 | -(NSMutableArray *)reloadCalendarView:(NSDate *)date selectDate:(NSDate *)selectDate needDays:(int)days showType:(CalendarShowType)type isEnable:(BOOL)isEnable priceModelArr:(NSArray *)arr; 31 | 32 | - (NSMutableArray *)reloadCalendarView:(NSDate *)date selectDate:(NSDate *)selectDate needDays:(int)days showType:(CalendarShowType)type priceModelArr:(NSArray *)arr; 33 | 34 | 35 | - (NSMutableArray *)reloadCalendarView:(NSDate *)date selectDate:(NSDate *)selectDate needDays:(int)days showType:(CalendarShowType)type; 36 | - (void)selectLogic:(RMCalendarModel *)dayModel; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /RMCalendar/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.ruanman.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /RMCalendar/MJExtension/MJProperty.h: -------------------------------------------------------------------------------- 1 | // 2 | // MJProperty.h 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 15/4/17. 6 | // Copyright (c) 2015年 小码哥. All rights reserved. 7 | // 包装一个成员属性 8 | 9 | #import 10 | #import 11 | #import "MJType.h" 12 | 13 | /** 14 | * 包装一个成员 15 | */ 16 | @interface MJProperty : NSObject 17 | /** 成员属性 */ 18 | @property (nonatomic, assign) objc_property_t property; 19 | /** 成员属性名 */ 20 | @property (nonatomic, readonly) NSString *name; 21 | 22 | /** 成员变量的类型 */ 23 | @property (nonatomic, readonly) MJType *type; 24 | /** 成员来源于哪个类(可能是父类) */ 25 | @property (nonatomic, assign) Class srcClass; 26 | 27 | /**** 同一个成员变量 - 父类和子类的行为可能不一致(key、keys、objectClassInArray) ****/ 28 | /** 对应着字典中的key */ 29 | - (void)setKey:(NSString *)key forClass:(Class)c; 30 | - (NSString *)keyFromClass:(Class)c; 31 | 32 | /** 对应着字典中的多级key */ 33 | - (NSArray *)keysFromClass:(Class)c; 34 | 35 | /** 模型数组中的模型类型 */ 36 | - (void)setObjectClassInArray:(Class)objectClass forClass:(Class)c; 37 | - (Class)objectClassInArrayFromClass:(Class)c; 38 | /**** 同一个成员变量 - 父类和子类的行为可能不一致(key、keys、objectClassInArray) ****/ 39 | 40 | /** 41 | * 设置成员变量的值 42 | */ 43 | - (void)setValue:(id)value forObject:(id)object; 44 | /** 45 | * 得到成员变量的值 46 | */ 47 | - (id)valueFromObject:(id)object; 48 | 49 | /** 50 | * 初始化 51 | */ 52 | + (instancetype)cachedPropertyWithProperty:(objc_property_t)property; 53 | @end 54 | -------------------------------------------------------------------------------- /Class/Model/RMCalendarModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMCalendarModel.m 3 | // RMCalendar 4 | // 5 | // Created by 迟浩东 on 15/7/15. 6 | // Copyright © 2015年 迟浩东(http://www.ruanman.net). All rights reserved. 7 | // 8 | 9 | #import "RMCalendarModel.h" 10 | #import "NSDate+RMCalendarLogic.h" 11 | 12 | @implementation RMCalendarModel 13 | 14 | - (instancetype)initWithYear:(NSUInteger)year month:(NSUInteger)month day:(NSUInteger)day { 15 | self = [super init]; 16 | if (!self) return nil; 17 | self.year = year; 18 | self.month = month; 19 | self.day = day; 20 | return self; 21 | } 22 | 23 | + (instancetype)calendarWithYear:(NSUInteger)year month:(NSUInteger)month day:(NSUInteger)day { 24 | return [[self alloc] initWithYear:year month:month day:day]; 25 | } 26 | 27 | //返回当前天的NSDate对象 28 | - (NSDate *)date 29 | { 30 | NSDateComponents *c = [[NSDateComponents alloc] init]; 31 | c.year = self.year; 32 | c.month = self.month; 33 | c.day = self.day; 34 | return [[NSCalendar currentCalendar] dateFromComponents:c]; 35 | } 36 | 37 | //返回当前天的NSString对象 38 | - (NSString *)toString 39 | { 40 | NSDate *date = [self date]; 41 | NSString *string = [date stringFromDate:date]; 42 | return string; 43 | } 44 | 45 | 46 | //返回星期 47 | - (NSString *)getWeek 48 | { 49 | 50 | NSDate *date = [self date]; 51 | 52 | NSString *week_str = [date compareIfTodayWithDate]; 53 | 54 | return week_str; 55 | } 56 | 57 | ////判断是不是同一天 58 | //- (BOOL)isEqualTo:(CalendarDayModel *)day 59 | //{ 60 | // BOOL isEqual = (self.year == day.year) && (self.month == day.month) && (self.day == day.day); 61 | // return isEqual; 62 | //} 63 | @end 64 | -------------------------------------------------------------------------------- /Class/Model/RMCalendarModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // RMCalendarModel.h 3 | // RMCalendar 4 | // 5 | // Created by 迟浩东 on 15/7/15. 6 | // Copyright © 2015年 迟浩东(http://www.ruanman.net). All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TicketModel.h" 11 | 12 | typedef NS_ENUM(NSInteger, CellDayType) { 13 | CellDayTypeEmpty, //不显示 14 | CellDayTypePast, //过去的日期 15 | CellDayTypeFutur, //将来的日期 16 | CellDayTypeWeek, //周末 17 | CellDayTypeClick //被点击的日期 18 | 19 | }; 20 | 21 | @interface RMCalendarModel : NSObject 22 | 23 | /** 24 | * 显示样式 25 | */ 26 | @property (assign, nonatomic) CellDayType style; 27 | /** 28 | * 年 29 | */ 30 | @property (nonatomic, assign) NSUInteger year; 31 | /** 32 | * 月 33 | */ 34 | @property (nonatomic, assign) NSUInteger month; 35 | /** 36 | * 周 37 | */ 38 | @property (nonatomic, assign) NSUInteger week; 39 | /** 40 | * 日 41 | */ 42 | @property (nonatomic, assign) NSUInteger day; 43 | 44 | /** 45 | * 票价模型 46 | */ 47 | @property (nonatomic, strong) TicketModel *ticketModel; 48 | /** 49 | * 判断如果当前日期没有价格,是否可以被点击 50 | */ 51 | @property (nonatomic, assign) BOOL isEnable; 52 | 53 | @property (nonatomic, strong) NSString *Chinese_calendar;//农历 54 | @property (nonatomic, assign) BOOL isChineseCalendar; 55 | @property (nonatomic, strong) NSString *holiday;//节日 56 | 57 | 58 | + (instancetype)calendarWithYear:(NSUInteger)year month:(NSUInteger)month day:(NSUInteger)day; 59 | - (instancetype)initWithYear:(NSUInteger)year month:(NSUInteger)month day:(NSUInteger)day; 60 | - (NSDate *)date;//返回当前天的NSDate对象 61 | - (NSString *)toString;//返回当前天的NSString对象 62 | - (NSString *)getWeek; //返回星期 63 | 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /RMCalendar.xcodeproj/project.xcworkspace/xcshareddata/RMCalendar.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 59313485-6EF1-4326-A419-3C7AEEBFBD5F 9 | IDESourceControlProjectName 10 | RMCalendar 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | AC1A553D4D6C0F6FE06F6E60C8CA2E5F97003E1F 14 | https://github.com/chihaodong/RMCalendar.git 15 | 16 | IDESourceControlProjectPath 17 | RMCalendar.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | AC1A553D4D6C0F6FE06F6E60C8CA2E5F97003E1F 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/chihaodong/RMCalendar.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | AC1A553D4D6C0F6FE06F6E60C8CA2E5F97003E1F 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | AC1A553D4D6C0F6FE06F6E60C8CA2E5F97003E1F 36 | IDESourceControlWCCName 37 | RMCalendar 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /RMCalendar/MJExtension/NSObject+MJCoding.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+MJCoding.m 3 | // MJExtension 4 | // 5 | // Created by mj on 14-1-15. 6 | // Copyright (c) 2014年 小码哥. All rights reserved. 7 | // 8 | 9 | #import "NSObject+MJCoding.h" 10 | #import "NSObject+MJProperty.h" 11 | #import "MJProperty.h" 12 | 13 | @implementation NSObject (MJCoding) 14 | 15 | - (void)encode:(NSCoder *)encoder 16 | { 17 | Class aClass = [self class]; 18 | 19 | NSArray *allowedCodingPropertyNames = [aClass totalAllowedCodingPropertyNames]; 20 | NSArray *ignoredCodingPropertyNames = [aClass totalIgnoredCodingPropertyNames]; 21 | 22 | [aClass enumerateProperties:^(MJProperty *property, BOOL *stop) { 23 | if (allowedCodingPropertyNames.count && ![allowedCodingPropertyNames containsObject:property.name]) return; 24 | // 检测是否被忽略 25 | if ([ignoredCodingPropertyNames containsObject:property.name]) return; 26 | 27 | id value = [property valueFromObject:self]; 28 | if (value == nil) return; 29 | [encoder encodeObject:value forKey:property.name]; 30 | }]; 31 | } 32 | 33 | - (void)decode:(NSCoder *)decoder 34 | { 35 | Class aClass = [self class]; 36 | 37 | NSArray *allowedCodingPropertyNames = [aClass totalAllowedCodingPropertyNames]; 38 | NSArray *ignoredCodingPropertyNames = [aClass totalIgnoredCodingPropertyNames]; 39 | 40 | [aClass enumerateProperties:^(MJProperty *property, BOOL *stop) { 41 | if (allowedCodingPropertyNames.count && ![allowedCodingPropertyNames containsObject:property.name]) return; 42 | // 检测是否被忽略 43 | if ([ignoredCodingPropertyNames containsObject:property.name]) return; 44 | 45 | id value = [decoder decodeObjectForKey:property.name]; 46 | if (value == nil) return; 47 | [property setValue:value forObject:self]; 48 | }]; 49 | } 50 | @end 51 | -------------------------------------------------------------------------------- /Class/Controller/RMCalendarController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RMCalendarController.h 3 | // RMCalendar 4 | // 5 | // Created by 迟浩东 on 15/7/15. 6 | // Copyright © 2015年 迟浩东(http://www.ruanman.net). All rights reserved. 7 | // 8 | 9 | #import 10 | #import "RMCalendarLogic.h" 11 | /** 12 | * 选中日起,回掉结果 13 | * 14 | * @param model 返回模型 15 | */ 16 | typedef void (^CalendarBlock)(RMCalendarModel *model); 17 | 18 | 19 | /** 20 | * 起始页面 21 | */ 22 | @interface RMCalendarController : UIViewController 23 | 24 | /** 25 | * UICollectionView 对象,用于显示布局,类似UITableView 26 | */ 27 | @property(nonatomic ,strong) UICollectionView* collectionView; 28 | /** 29 | * 用于存放日期模型数组 30 | */ 31 | @property(nonatomic ,strong) NSMutableArray *calendarMonth; 32 | /** 33 | * 逻辑处理 34 | */ 35 | @property(nonatomic ,strong) RMCalendarLogic *calendarLogic; 36 | /** 37 | * 回调 38 | */ 39 | @property(nonatomic, copy) CalendarBlock calendarBlock; 40 | /** 41 | * 天数 42 | */ 43 | @property(nonatomic, assign) int days; 44 | /** 45 | * 展示类型 46 | */ 47 | @property(nonatomic, assign) CalendarShowType type; 48 | /** 49 | * 用于存放价格模型数组 50 | */ 51 | @property(nonatomic, retain) NSMutableArray *modelArr; 52 | /** 53 | * 无价格的日期是否可点击 默认为NO 54 | */ 55 | @property(nonatomic, assign) BOOL isEnable; 56 | /** 57 | * 是否展示农历 默认为NO 58 | */ 59 | @property(nonatomic, assign) BOOL isDisplayChineseCalendar; 60 | 61 | /** 62 | * 初始化对象 63 | * 64 | * @param days 显示总天数,默认365天 65 | * @param type 显示类型,详细请见 枚举的定义 66 | * 67 | * @return 当前对象 68 | */ 69 | - (instancetype)initWithDays:(int)days showType:(CalendarShowType)type; 70 | 71 | - (instancetype)initWithDays:(int)days showType:(CalendarShowType)type modelArrar:(NSMutableArray *)modelArr; 72 | 73 | + (instancetype)calendarWithDays:(int)days showType:(CalendarShowType)type; 74 | 75 | + (instancetype)calendarWithDays:(int)days showType:(CalendarShowType)type modelArrar:(NSMutableArray *)modelArr; 76 | 77 | 78 | @end 79 | -------------------------------------------------------------------------------- /RMCalendar/MJExtension/MJType.m: -------------------------------------------------------------------------------- 1 | // 2 | // MJType.m 3 | // MJExtension 4 | // 5 | // Created by mj on 14-1-15. 6 | // Copyright (c) 2014年 小码哥. All rights reserved. 7 | // 8 | 9 | #import "MJType.h" 10 | #import "MJExtension.h" 11 | #import "MJFoundation.h" 12 | #import "MJConst.h" 13 | 14 | @implementation MJType 15 | 16 | static NSMutableDictionary *_cachedTypes; 17 | + (void)load 18 | { 19 | _cachedTypes = [NSMutableDictionary dictionary]; 20 | } 21 | 22 | + (instancetype)cachedTypeWithCode:(NSString *)code 23 | { 24 | MJAssertParamNotNil2(code, nil); 25 | 26 | MJType *type = _cachedTypes[code]; 27 | if (type == nil) { 28 | type = [[self alloc] init]; 29 | type.code = code; 30 | _cachedTypes[code] = type; 31 | } 32 | return type; 33 | } 34 | 35 | - (void)setCode:(NSString *)code 36 | { 37 | _code = code; 38 | 39 | MJAssertParamNotNil(code); 40 | 41 | if ([code isEqualToString:MJTypeId]) { 42 | _idType = YES; 43 | } else if (code.length == 0) { 44 | _KVCDisabled = YES; 45 | } else if (code.length > 3 && [code hasPrefix:@"@\""]) { 46 | // 去掉@"和",截取中间的类型名称 47 | _code = [code substringWithRange:NSMakeRange(2, code.length - 3)]; 48 | _typeClass = NSClassFromString(_code); 49 | _fromFoundation = [MJFoundation isClassFromFoundation:_typeClass]; 50 | _numberType = (_typeClass == [NSNumber class] || [_typeClass isSubclassOfClass:[NSNumber class]]); 51 | } else if ([code isEqualToString:MJTypeSEL] || 52 | [code isEqualToString:MJTypeIvar] || 53 | [code isEqualToString:MJTypeMethod]) { 54 | _KVCDisabled = YES; 55 | } 56 | 57 | // 是否为数字类型 58 | NSString *lowerCode = _code.lowercaseString; 59 | NSArray *numberTypes = @[MJTypeInt, MJTypeFloat, MJTypeDouble, MJTypeLong, MJTypeChar]; 60 | if ([numberTypes containsObject:lowerCode]) { 61 | _numberType = YES; 62 | } 63 | } 64 | @end 65 | -------------------------------------------------------------------------------- /RMCalendar.xcodeproj/xcuserdata/chihaodong.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 14 | 15 | 16 | 18 | 30 | 31 | 32 | 34 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /RMCalendar/MJExtension/MJConst.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __MJConst__H__ 3 | #define __MJConst__H__ 4 | 5 | #import 6 | 7 | // 过期 8 | #define MJDeprecated(instead) NS_DEPRECATED(2_0, 2_0, 2_0, 2_0, instead) 9 | 10 | #ifdef DEBUG // 调试状态 11 | // 打开LOG功能 12 | #define MJLog(...) NSLog(__VA_ARGS__) 13 | #else // 发布状态 14 | // 关闭LOG功能 15 | #define MJLog(...) 16 | #endif 17 | 18 | // 构建错误 19 | #define MJBuildError(error, msg) \ 20 | if (error) *error = [NSError errorWithDomain:msg code:250 userInfo:nil]; 21 | 22 | /** 23 | * 断言 24 | * @param condition 条件 25 | * @param returnValue 返回值 26 | */ 27 | #define MJAssertError(condition, returnValue, error, msg) \ 28 | if ((condition) == NO) { \ 29 | MJBuildError(error, msg); \ 30 | return returnValue;\ 31 | } 32 | 33 | #define MJAssert2(condition, returnValue) \ 34 | if ((condition) == NO) return returnValue; 35 | 36 | /** 37 | * 断言 38 | * @param condition 条件 39 | */ 40 | #define MJAssert(condition) MJAssert2(condition, ) 41 | 42 | /** 43 | * 断言 44 | * @param param 参数 45 | * @param returnValue 返回值 46 | */ 47 | #define MJAssertParamNotNil2(param, returnValue) \ 48 | MJAssert2((param) != nil, returnValue) 49 | 50 | /** 51 | * 断言 52 | * @param param 参数 53 | */ 54 | #define MJAssertParamNotNil(param) MJAssertParamNotNil2(param, ) 55 | 56 | /** 57 | * 打印所有的属性 58 | */ 59 | #define MJLogAllIvars \ 60 | -(NSString *)description \ 61 | { \ 62 | return [self keyValues].description; \ 63 | } 64 | 65 | /** 66 | * 类型(属性类型) 67 | */ 68 | extern NSString *const MJTypeInt; 69 | extern NSString *const MJTypeFloat; 70 | extern NSString *const MJTypeDouble; 71 | extern NSString *const MJTypeLong; 72 | extern NSString *const MJTypeLongLong; 73 | extern NSString *const MJTypeChar; 74 | extern NSString *const MJTypeBOOL; 75 | extern NSString *const MJTypePointer; 76 | 77 | extern NSString *const MJTypeIvar; 78 | extern NSString *const MJTypeMethod; 79 | extern NSString *const MJTypeBlock; 80 | extern NSString *const MJTypeClass; 81 | extern NSString *const MJTypeSEL; 82 | extern NSString *const MJTypeId; 83 | 84 | #endif -------------------------------------------------------------------------------- /Class/Category/UIView+CustomFrame.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+CustomFrame.m 3 | // RMCalendar 4 | // 5 | // Created by 迟浩东 on 15/4/30. 6 | // Copyright (c) 2015年 CHD. All rights reserved. 7 | // 8 | 9 | #import "UIView+CustomFrame.h" 10 | 11 | @implementation UIView (CustomFrame) 12 | 13 | 14 | - (void)setX:(CGFloat)x 15 | { 16 | CGRect frame = self.frame; 17 | frame.origin.x = x; 18 | self.frame = frame; 19 | } 20 | 21 | - (void)setY:(CGFloat)y 22 | { 23 | CGRect frame = self.frame; 24 | frame.origin.y = y; 25 | self.frame = frame; 26 | } 27 | 28 | - (CGFloat)x 29 | { 30 | return self.frame.origin.x; 31 | } 32 | 33 | - (CGFloat)y 34 | { 35 | return self.frame.origin.y; 36 | } 37 | 38 | - (void)setCenterX:(CGFloat)centerX 39 | { 40 | CGPoint center = self.center; 41 | center.x = centerX; 42 | self.center = center; 43 | } 44 | 45 | - (CGFloat)centerX 46 | { 47 | return self.center.x; 48 | } 49 | 50 | - (void)setCenterY:(CGFloat)centerY 51 | { 52 | CGPoint center = self.center; 53 | center.y = centerY; 54 | self.center = center; 55 | } 56 | 57 | - (CGFloat)centerY 58 | { 59 | return self.center.y; 60 | } 61 | 62 | - (void)setWidth:(CGFloat)width 63 | { 64 | CGRect frame = self.frame; 65 | frame.size.width = width; 66 | self.frame = frame; 67 | } 68 | 69 | - (void)setHeight:(CGFloat)height 70 | { 71 | CGRect frame = self.frame; 72 | frame.size.height = height; 73 | self.frame = frame; 74 | } 75 | 76 | - (CGFloat)height 77 | { 78 | return self.frame.size.height; 79 | } 80 | 81 | - (CGFloat)width 82 | { 83 | return self.frame.size.width; 84 | } 85 | 86 | - (void)setSize:(CGSize)size 87 | { 88 | CGRect frame = self.frame; 89 | frame.size = size; 90 | self.frame = frame; 91 | } 92 | 93 | - (CGSize)size 94 | { 95 | return self.frame.size; 96 | } 97 | 98 | - (void)setOrigin:(CGPoint)origin 99 | { 100 | CGRect frame = self.frame; 101 | frame.origin = origin; 102 | self.frame = frame; 103 | } 104 | 105 | - (CGPoint)origin 106 | { 107 | return self.frame.origin; 108 | } 109 | @end 110 | -------------------------------------------------------------------------------- /RMCalendar/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // RMCalendar 4 | // 5 | // Created by 迟浩东 on 15/7/1. 6 | // Copyright (c) 2015年 迟浩东. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /RMCalendar/MJExtension/NSString+MJExtension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+MJExtension.m 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 15/6/7. 6 | // Copyright (c) 2015年 小码哥. All rights reserved. 7 | // 8 | 9 | #import "NSString+MJExtension.h" 10 | 11 | @implementation NSString (MJExtension) 12 | - (NSString *)underlineFromCamel 13 | { 14 | if (self.length == 0) return self; 15 | NSMutableString *string = [NSMutableString string]; 16 | for (NSUInteger i = 0; i= 2) [string appendString:[cmp substringFromIndex:1]]; 40 | } else { 41 | [string appendString:cmp]; 42 | } 43 | } 44 | return string; 45 | } 46 | 47 | - (NSString *)firstCharLower 48 | { 49 | if (self.length == 0) return self; 50 | NSMutableString *string = [NSMutableString string]; 51 | [string appendString:[NSString stringWithFormat:@"%c", [self characterAtIndex:0]].lowercaseString]; 52 | if (self.length >= 2) [string appendString:[self substringFromIndex:1]]; 53 | return string; 54 | } 55 | 56 | - (NSString *)firstCharUpper 57 | { 58 | if (self.length == 0) return self; 59 | NSMutableString *string = [NSMutableString string]; 60 | [string appendString:[NSString stringWithFormat:@"%c", [self characterAtIndex:0]].uppercaseString]; 61 | if (self.length >= 2) [string appendString:[self substringFromIndex:1]]; 62 | return string; 63 | } 64 | @end 65 | -------------------------------------------------------------------------------- /Class/View/RMCalendarMonthHeaderView.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMCalendarMonthHeaderView.m 3 | // RMCalendar 4 | // 5 | // Created by 迟浩东 on 15/7/15. 6 | // Copyright © 2015年 迟浩东(http://www.ruanman.net). All rights reserved. 7 | // 8 | 9 | #import "RMCalendarMonthHeaderView.h" 10 | 11 | #define CATDayLabelWidth ([UIScreen mainScreen].bounds.size.width/7) 12 | #define CATDayLabelHeight 20.0f 13 | 14 | #define COLOR_THEME1 ([UIColor redColor]) 15 | #define COLOR_THEME ([UIColor colorWithRed:26/256.0 green:168/256.0 blue:186/256.0 alpha:1]) 16 | 17 | @interface RMCalendarMonthHeaderView() 18 | 19 | @property (weak, nonatomic) UILabel *day1OfTheWeekLabel; 20 | @property (weak, nonatomic) UILabel *day2OfTheWeekLabel; 21 | @property (weak, nonatomic) UILabel *day3OfTheWeekLabel; 22 | @property (weak, nonatomic) UILabel *day4OfTheWeekLabel; 23 | @property (weak, nonatomic) UILabel *day5OfTheWeekLabel; 24 | @property (weak, nonatomic) UILabel *day6OfTheWeekLabel; 25 | @property (weak, nonatomic) UILabel *day7OfTheWeekLabel; 26 | 27 | @end 28 | 29 | @implementation RMCalendarMonthHeaderView 30 | 31 | - (instancetype)initWithFrame:(CGRect)frame 32 | { 33 | self = [super initWithFrame:frame]; 34 | if (self) { 35 | // Initialization code 36 | [self initWithHeader]; 37 | } 38 | return self; 39 | } 40 | 41 | - (void)initWithHeader 42 | { 43 | self.clipsToBounds = YES; 44 | CGFloat headerWidth = [UIScreen mainScreen].bounds.size.width; 45 | //月份 46 | UILabel *masterLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.f, 10.0f, headerWidth, 30.f)]; 47 | [masterLabel setTextAlignment:NSTextAlignmentCenter]; 48 | [masterLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:17.0f]]; 49 | self.masterLabel = masterLabel; 50 | self.masterLabel.textColor = COLOR_THEME; 51 | [self addSubview:self.masterLabel]; 52 | CGFloat yOffset = 45.0f; 53 | NSArray *textArray = @[@"日", @"一", @"二", @"三", @"四", @"五", @"六"]; 54 | for (int i = 0; i < textArray.count; i++) { 55 | [self initHeaderWeekText:textArray[i] titleColor:COLOR_THEME x:CATDayLabelWidth * i y:yOffset]; 56 | } 57 | 58 | } 59 | 60 | // 初始化数据 61 | - (void)initHeaderWeekText:(NSString *)text titleColor:(UIColor *)color x:(CGFloat)x y:(CGFloat)y { 62 | UILabel *titleText = [[UILabel alloc]initWithFrame:CGRectMake(x, y, CATDayLabelWidth, CATDayLabelHeight)]; 63 | [titleText setFont:[UIFont fontWithName:@"HelveticaNeue-Light" size:15.0f]]; 64 | titleText.textAlignment = NSTextAlignmentCenter; 65 | titleText.textColor = color; 66 | titleText.text = text; 67 | [self addSubview:titleText]; 68 | } 69 | 70 | @end 71 | 72 | -------------------------------------------------------------------------------- /RMCalendar/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // RMCalendar 4 | // 5 | // Created by 迟浩东 on 15/7/1. 6 | // Copyright (c) 2015年 迟浩东. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "RMCalendarController.h" 11 | #import "MJExtension.h" 12 | #import "TicketModel.h" 13 | 14 | @interface ViewController () 15 | 16 | @end 17 | 18 | @implementation ViewController 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | // Do any additional setup after loading the view, typically from a nib. 23 | } 24 | 25 | - (void)didReceiveMemoryWarning { 26 | [super didReceiveMemoryWarning]; 27 | // Dispose of any resources that can be recreated. 28 | } 29 | - (IBAction)btnClick { 30 | // CalendarShowTypeMultiple 显示多月 31 | // CalendarShowTypeSingle 显示单月 32 | RMCalendarController *c = [RMCalendarController calendarWithDays:365 showType:CalendarShowTypeMultiple]; 33 | 34 | // 此处用到MJ大神开发的框架,根据自己需求调整是否需要 35 | c.modelArr = [TicketModel objectArrayWithKeyValuesArray:@[@{@"year":@2015, @"month":@7, @"day":@22, 36 | @"ticketCount":@194, @"ticketPrice":@283}, 37 | @{@"year":@2015, @"month":@7, @"day":@17, 38 | @"ticketCount":@91, @"ticketPrice":@223}, 39 | @{@"year":@2015, @"month":@10, @"day":@4, 40 | @"ticketCount":@91, @"ticketPrice":@23}, 41 | @{@"year":@2015, @"month":@7, @"day":@8, 42 | @"ticketCount":@2, @"ticketPrice":@203}, 43 | @{@"year":@2015, @"month":@7, @"day":@28, 44 | @"ticketCount":@2, @"ticketPrice":@103}, 45 | @{@"year":@2015, @"month":@7, @"day":@18, 46 | @"ticketCount":@0, @"ticketPrice":@153}]]; //最后一条数据ticketCount 为0时不显示 47 | // 是否展现农历 48 | c.isDisplayChineseCalendar = YES; 49 | 50 | // YES 没有价格的日期可点击 51 | // NO 没有价格的日期不可点击 52 | c.isEnable = YES; 53 | c.title = @"单价日历 软曼网"; 54 | c.calendarBlock = ^(RMCalendarModel *model) { 55 | if (model.ticketModel.ticketCount) { 56 | NSLog(@"%lu-%lu-%lu-票价%.1f",(unsigned long)model.year,(unsigned long)model.month,(unsigned long)model.day, model.ticketModel.ticketPrice); 57 | } else { 58 | NSLog(@"%lu-%lu-%lu",(unsigned long)model.year,(unsigned long)model.month,(unsigned long)model.day); 59 | } 60 | }; 61 | [self.navigationController pushViewController:c animated:YES]; 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RMCalendar 单价日历 2 | 3 | 实现功能: 4 | 5 | 2015年7月16日更新 6 | 7 | 添加农历功能,对细节优化修复 8 | 9 | 主要是在日历上显示 当日对应的单价,类似携程、同城、去哪等旅游APP的日历,可以展现当日的票价等功能。 10 | 11 | ![image](https://github.com/chihaodong/RMCalendar/blob/master/Preview/preview-2@2x.jpg) 12 | ![image](https://github.com/chihaodong/RMCalendar/blob/master/Preview/preview-3@2x.jpg) 13 | ![image](https://github.com/chihaodong/RMCalendar/blob/master/Preview/preview-4@2x.jpg) 14 | ![image](https://github.com/chihaodong/RMCalendar/blob/master/Preview/preview-5@2x.jpg) 15 | 16 | # 使用方法 17 | 18 | 将项目下的Class文件夹复制到项目中 19 | 导入对应头文件 #import "RMCalendarController.h" 入口 20 | 21 | 创建对象 (有多种方法,具体看代码) 22 | ``` 23 | RMCalendarController *c = [RMCalendarController calendarWithDays:365 showType:CalendarShowTypeMultiple]; 24 | c.isDisplayChineseCalendar = YES; // 增加农历展现功能 默认不展现 25 | c.isEnable = YES; // 设置是否显示 无价格时可点击 26 | c.modelArr = "TicketModel模型数组"; //具体属性需看 TicketModel.h 文件 传入格式请按照 下面例子 27 | // 返回结果回调 28 | c.calendarBlock = ^(RMCalendarModel *model) { 29 | if (model.ticketModel.ticketCount) { 30 | NSLog(@"%lu-%lu-%lu-票价%.1f",(unsigned long)model.year,(unsigned long)model.month,(unsigned long)model.day, model.ticketModel.ticketPrice); 31 | } else { 32 | NSLog(@"%lu-%lu-%lu",(unsigned long)model.year,(unsigned long)model.month,(unsigned long)model.day); 33 | } 34 | }; 35 | ``` 36 | 37 | 如:此处用到MJ的第三方框架将字典数组模型转为模型对象,可根据情况是否使用 38 | ``` 39 | c.modelArr = [TicketModel objectArrayWithKeyValuesArray:@[@{@"year":@2015, @"month":@7, @"day":@6, 40 | @"ticketCount":@194, @"ticketPrice":@283}, 41 | @{@"year":@2015, @"month":@7, @"day":@7, 42 | @"ticketCount":@91, @"ticketPrice":@223}, 43 | @{@"year":@2015, @"month":@10, @"day":@4, 44 | @"ticketCount":@91, @"ticketPrice":@23}, 45 | @{@"year":@2015, @"month":@7, @"day":@8, 46 | @"ticketCount":@2, @"ticketPrice":@203}, 47 | @{@"year":@2015, @"month":@7, @"day":@28, 48 | @"ticketCount":@2, @"ticketPrice":@103}, 49 | @{@"year":@2015, @"month":@7, @"day":@18, 50 | @"ticketCount":@0, @"ticketPrice":@153}]]; //最后一条数据ticketCount 为0时不显示 51 | 52 | ``` 53 | 54 | #目录结构 55 | Category 一些扩展的方法 56 | Controller 控制器 57 | Logic 业务逻辑 58 | Model 模型 59 | Other 资源图片 60 | View 视图 61 | #声明 AND 致谢 62 | 1、此处用到MJ的模型转换框架:https://github.com/CoderMJLee/MJExtension 63 | 2、日历源代码是由我爱吃番茄开发,只是在原来基础上增加自己的需求和代码优化工作,实现单价日历效果,再次感谢原作者。http://code4app.com/ios/%E4%B8%80%E6%AC%BE%E7%AE%80%E5%8D%95%E7%9A%84%E6%97%A5%E5%8E%86%E6%8E%A7%E4%BB%B6/53fa8a8b933bf0fe0d8b482b 64 | 65 | #版权 66 | 1、第三方框架版权归于原作者,MJ大神 67 | 2、日历部分源码属于原作者:我爱吃番茄 68 | 3、二次开发版权归于本人 69 | #网站 70 | 软曼网:http://www.ruanman.net/ 提供Windows 10系统下载,iOS 开发技术分享,欢迎大家支持 QQ技术交流群:33415610 71 | -------------------------------------------------------------------------------- /RMCalendar/MJExtension/MJProperty.m: -------------------------------------------------------------------------------- 1 | // 2 | // MJProperty.m 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 15/4/17. 6 | // Copyright (c) 2015年 小码哥. All rights reserved. 7 | // 8 | 9 | #import "MJProperty.h" 10 | #import "MJFoundation.h" 11 | #import "MJConst.h" 12 | 13 | @interface MJProperty() 14 | @property (strong, nonatomic) NSMutableDictionary *keyDict; 15 | @property (strong, nonatomic) NSMutableDictionary *keysDict; 16 | @property (strong, nonatomic) NSMutableDictionary *objectClassInArrayDict; 17 | @end 18 | 19 | @implementation MJProperty 20 | 21 | - (NSMutableDictionary *)keyDict 22 | { 23 | if (!_keyDict) { 24 | self.keyDict = [NSMutableDictionary dictionary]; 25 | } 26 | return _keyDict; 27 | } 28 | 29 | - (NSMutableDictionary *)keysDict 30 | { 31 | if (!_keysDict) { 32 | self.keysDict = [NSMutableDictionary dictionary]; 33 | } 34 | return _keysDict; 35 | } 36 | 37 | - (NSMutableDictionary *)objectClassInArrayDict 38 | { 39 | if (!_objectClassInArrayDict) { 40 | self.objectClassInArrayDict = [NSMutableDictionary dictionary]; 41 | } 42 | return _objectClassInArrayDict; 43 | } 44 | 45 | + (instancetype)cachedPropertyWithProperty:(objc_property_t)property 46 | { 47 | MJProperty *propertyObj = objc_getAssociatedObject(self, property); 48 | if (propertyObj == nil) { 49 | propertyObj = [[self alloc] init]; 50 | propertyObj.property = property; 51 | objc_setAssociatedObject(self, property, propertyObj, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 52 | } 53 | return propertyObj; 54 | } 55 | 56 | - (void)setProperty:(objc_property_t)property 57 | { 58 | _property = property; 59 | 60 | MJAssertParamNotNil(property); 61 | 62 | // 1.属性名 63 | _name = @(property_getName(property)); 64 | 65 | // 2.成员类型 66 | NSString *attrs = @(property_getAttributes(property)); 67 | NSUInteger loc = 1; 68 | NSUInteger len = [attrs rangeOfString:@","].location - loc; 69 | _type = [MJType cachedTypeWithCode:[attrs substringWithRange:NSMakeRange(loc, len)]]; 70 | } 71 | 72 | /** 73 | * 获得成员变量的值 74 | */ 75 | - (id)valueFromObject:(id)object 76 | { 77 | if (_type.KVCDisabled) return [NSNull null]; 78 | return [object valueForKey:_name]; 79 | } 80 | 81 | /** 82 | * 设置成员变量的值 83 | */ 84 | - (void)setValue:(id)value forObject:(id)object 85 | { 86 | if (_type.KVCDisabled || value == nil) return; 87 | [object setValue:value forKey:_name]; 88 | } 89 | 90 | /** 对应着字典中的key */ 91 | - (void)setKey:(NSString *)key forClass:(Class)c 92 | { 93 | if (!key) return; 94 | self.keyDict[NSStringFromClass(c)] = key; 95 | // 如果有多级映射 96 | [self setKeys:[key componentsSeparatedByString:@"."] forClass:c]; 97 | } 98 | - (NSString *)keyFromClass:(Class)c 99 | { 100 | return self.keyDict[NSStringFromClass(c)]; 101 | } 102 | 103 | /** 对应着字典中的多级key */ 104 | - (void)setKeys:(NSArray *)keys forClass:(Class)c 105 | { 106 | if (!keys) return; 107 | self.keysDict[NSStringFromClass(c)] = keys; 108 | } 109 | - (NSArray *)keysFromClass:(Class)c 110 | { 111 | return self.keysDict[NSStringFromClass(c)]; 112 | } 113 | 114 | /** 模型数组中的模型类型 */ 115 | - (void)setObjectClassInArray:(Class)objectClass forClass:(Class)c 116 | { 117 | if (!objectClass) return; 118 | self.objectClassInArrayDict[NSStringFromClass(c)] = objectClass; 119 | } 120 | - (Class)objectClassInArrayFromClass:(Class)c 121 | { 122 | return self.objectClassInArrayDict[NSStringFromClass(c)]; 123 | } 124 | @end 125 | -------------------------------------------------------------------------------- /RMCalendar/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /RMCalendar/MJExtension/NSObject+MJProperty.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+MJProperty.h 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 15/4/17. 6 | // Copyright (c) 2015年 小码哥. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class MJProperty, MJProperty; 12 | 13 | /** 14 | * 遍历所有类的block(父类) 15 | */ 16 | typedef void (^MJClassesEnumeration)(Class c, BOOL *stop); 17 | 18 | /** 19 | * 遍历成员变量用的block 20 | * 21 | * @param property 成员的包装对象 22 | * @param stop YES代表停止遍历,NO代表继续遍历 23 | */ 24 | typedef void (^MJPropertiesEnumeration)(MJProperty *property, BOOL *stop); 25 | 26 | /** 将属性名换为其他key去字典中取值 */ 27 | typedef NSDictionary * (^MJReplacedKeyFromPropertyName)(); 28 | typedef NSString * (^MJReplacedKeyFromPropertyName121)(NSString *propertyName); 29 | /** 数组中需要转换的模型类 */ 30 | typedef NSDictionary * (^MJObjectClassInArray)(); 31 | /** 用于过滤字典中的值 */ 32 | typedef id (^MJNewValueFormOldValue)(id object, id oldValue, MJProperty *property); 33 | 34 | /** 这个数组中的属性名才会进行字典和模型的转换 */ 35 | typedef NSArray * (^MJAllowedPropertyNames)(); 36 | /** 这个数组中的属性名才会进行归档 */ 37 | typedef NSArray * (^MJAllowedCodingPropertyNames)(); 38 | 39 | /** 这个数组中的属性名将会被忽略:不进行字典和模型的转换 */ 40 | typedef NSArray * (^MJIgnoredPropertyNames)(); 41 | /** 这个数组中的属性名将会被忽略:不进行归档 */ 42 | typedef NSArray * (^MJIgnoredCodingPropertyNames)(); 43 | 44 | @interface NSObject (MJProperty) 45 | #pragma mark - 遍历 46 | /** 47 | * 遍历所有的成员 48 | */ 49 | + (void)enumerateProperties:(MJPropertiesEnumeration)enumeration; 50 | 51 | /** 52 | * 遍历所有的类 53 | */ 54 | + (void)enumerateClasses:(MJClassesEnumeration)enumeration; 55 | + (void)enumerateAllClasses:(MJClassesEnumeration)enumeration; 56 | 57 | #pragma mark - 新值配置 58 | /** 59 | * 用于过滤字典中的值 60 | * 61 | * @param newValueFormOldValue 用于过滤字典中的值 62 | */ 63 | + (void)setupNewValueFormOldValue:(MJNewValueFormOldValue)newValueFormOldValue; 64 | + (id)getNewValueFormOldValue:(__weak id)oldValue object:(__weak id)object property:(__weak MJProperty *)property; 65 | 66 | #pragma mark - key配置 67 | /** 68 | * 将属性名换为其他key去字典中取值 69 | * 70 | * @param replacedKeyFromPropertyName 将属性名换为其他key去字典中取值 71 | */ 72 | + (void)setupReplacedKeyFromPropertyName:(MJReplacedKeyFromPropertyName)replacedKeyFromPropertyName; 73 | /** 74 | * 将属性名换为其他key去字典中取值 75 | * 76 | * @param replacedKeyFromPropertyName 将属性名换为其他key去字典中取值 77 | */ 78 | + (void)setupReplacedKeyFromPropertyName121:(MJReplacedKeyFromPropertyName121)replacedKeyFromPropertyName121; 79 | 80 | #pragma mark - array model class配置 81 | /** 82 | * 数组中需要转换的模型类 83 | * 84 | * @param objectClassInArray 数组中需要转换的模型类 85 | */ 86 | + (void)setupObjectClassInArray:(MJObjectClassInArray)objectClassInArray; 87 | 88 | #pragma mark - 属性白名单配置 89 | /** 90 | * 这个数组中的属性名才会进行字典和模型的转换 91 | * 92 | * @param allowedPropertyNames 这个数组中的属性名才会进行字典和模型的转换 93 | */ 94 | + (void)setupAllowedPropertyNames:(MJAllowedPropertyNames)allowedPropertyNames; 95 | 96 | /** 97 | * 这个数组中的属性名才会进行字典和模型的转换 98 | */ 99 | + (NSMutableArray *)totalAllowedPropertyNames; 100 | 101 | #pragma mark - 归档属性白名单配置 102 | /** 103 | * 这个数组中的属性名才会进行归档 104 | * 105 | * @param allowedCodingPropertyNames 这个数组中的属性名才会进行归档 106 | */ 107 | + (void)setupAllowedCodingPropertyNames:(MJAllowedCodingPropertyNames)allowedCodingPropertyNames; 108 | 109 | /** 110 | * 这个数组中的属性名才会进行字典和模型的转换 111 | */ 112 | + (NSMutableArray *)totalAllowedCodingPropertyNames; 113 | 114 | #pragma mark - 属性黑名单配置 115 | /** 116 | * 这个数组中的属性名将会被忽略:不进行字典和模型的转换 117 | * 118 | * @param ignoredPropertyNames 这个数组中的属性名将会被忽略:不进行字典和模型的转换 119 | */ 120 | + (void)setupIgnoredPropertyNames:(MJIgnoredPropertyNames)ignoredPropertyNames; 121 | 122 | /** 123 | * 这个数组中的属性名将会被忽略:不进行字典和模型的转换 124 | */ 125 | + (NSMutableArray *)totalIgnoredPropertyNames; 126 | 127 | #pragma mark - 归档属性黑名单配置 128 | /** 129 | * 这个数组中的属性名将会被忽略:不进行归档 130 | * 131 | * @param ignoredCodingPropertyNames 这个数组中的属性名将会被忽略:不进行归档 132 | */ 133 | + (void)setupIgnoredCodingPropertyNames:(MJIgnoredCodingPropertyNames)ignoredCodingPropertyNames; 134 | 135 | /** 136 | * 这个数组中的属性名将会被忽略:不进行归档 137 | */ 138 | + (NSMutableArray *)totalIgnoredCodingPropertyNames; 139 | @end -------------------------------------------------------------------------------- /RMCalendar.xcodeproj/xcuserdata/chd.xcuserdatad/xcschemes/RMCalendar.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 77 | 83 | 84 | 85 | 86 | 87 | 88 | 94 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /Class/View/RMCalendarCollectionViewLayout.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMCalendarCollectionViewLayout.m 3 | // RMCalendar 4 | // 5 | // Created by 迟浩东 on 15/7/15. 6 | // Copyright © 2015年 迟浩东(http://www.ruanman.net). All rights reserved. 7 | // 8 | 9 | #import "RMCalendarCollectionViewLayout.h" 10 | 11 | @implementation RMCalendarCollectionViewLayout 12 | 13 | - (instancetype)init 14 | { 15 | float screen = [UIScreen mainScreen].bounds.size.width; 16 | self = [super init]; 17 | if (self) { 18 | // 头部年月视图的大小 19 | self.headerReferenceSize = CGSizeMake(screen, 75.0f); 20 | // 每个Cell大小 -1是用作1个像素的间距 21 | self.itemSize = CGSizeMake(screen/7.0-1, screen/7.0); 22 | // 每行的最小间距 23 | self.minimumLineSpacing = 1.0f; 24 | // 每列的最小间距,设置Cell的大小已经留出1个像素大小,所以此处设置0即可 25 | self.minimumInteritemSpacing = 0.0f; 26 | // CollectionView视图的/上/左/下/右,的边距 27 | self.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0); 28 | } 29 | 30 | return self; 31 | } 32 | 33 | 34 | 35 | - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { 36 | 37 | NSMutableArray *answer = [[super layoutAttributesForElementsInRect:rect] mutableCopy]; 38 | UICollectionView * const cv = self.collectionView; 39 | CGPoint const contentOffset = cv.contentOffset; 40 | 41 | NSMutableIndexSet *missingSections = [NSMutableIndexSet indexSet]; 42 | for (UICollectionViewLayoutAttributes *layoutAttributes in answer) { 43 | if (layoutAttributes.representedElementCategory == UICollectionElementCategoryCell) { 44 | [missingSections addIndex:layoutAttributes.indexPath.section]; 45 | } 46 | } 47 | for (UICollectionViewLayoutAttributes *layoutAttributes in answer) { 48 | if ([layoutAttributes.representedElementKind isEqualToString:UICollectionElementKindSectionHeader]) { 49 | [missingSections removeIndex:layoutAttributes.indexPath.section]; 50 | } 51 | } 52 | 53 | [missingSections enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { 54 | 55 | NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:idx]; 56 | 57 | UICollectionViewLayoutAttributes *layoutAttributes = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:indexPath]; 58 | 59 | [answer addObject:layoutAttributes]; 60 | 61 | }]; 62 | 63 | for (UICollectionViewLayoutAttributes *layoutAttributes in answer) { 64 | 65 | if ([layoutAttributes.representedElementKind isEqualToString:UICollectionElementKindSectionHeader]) { 66 | 67 | NSInteger section = layoutAttributes.indexPath.section; 68 | NSInteger numberOfItemsInSection = [cv numberOfItemsInSection:section]; 69 | 70 | NSIndexPath *firstObjectIndexPath = [NSIndexPath indexPathForItem:0 inSection:section]; 71 | NSIndexPath *lastObjectIndexPath = [NSIndexPath indexPathForItem:MAX(0, (numberOfItemsInSection - 1)) inSection:section]; 72 | 73 | UICollectionViewLayoutAttributes *firstObjectAttrs; 74 | UICollectionViewLayoutAttributes *lastObjectAttrs; 75 | 76 | if (numberOfItemsInSection > 0) { 77 | firstObjectAttrs = [self layoutAttributesForItemAtIndexPath:firstObjectIndexPath]; 78 | lastObjectAttrs = [self layoutAttributesForItemAtIndexPath:lastObjectIndexPath]; 79 | } else { 80 | firstObjectAttrs = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader 81 | atIndexPath:firstObjectIndexPath]; 82 | lastObjectAttrs = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionFooter 83 | atIndexPath:lastObjectIndexPath]; 84 | } 85 | 86 | CGFloat headerHeight = CGRectGetHeight(layoutAttributes.frame); 87 | CGPoint origin = layoutAttributes.frame.origin; 88 | origin.y = MIN( 89 | MAX( 90 | contentOffset.y + cv.contentInset.top, 91 | (CGRectGetMinY(firstObjectAttrs.frame) - headerHeight) 92 | ), 93 | (CGRectGetMaxY(lastObjectAttrs.frame) - headerHeight) 94 | ); 95 | 96 | layoutAttributes.zIndex = 1024; 97 | layoutAttributes.frame = (CGRect){ 98 | .origin = origin, 99 | .size = layoutAttributes.frame.size 100 | }; 101 | 102 | } 103 | 104 | } 105 | 106 | return answer; 107 | 108 | } 109 | 110 | - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBound { 111 | 112 | return YES; 113 | 114 | } 115 | 116 | @end 117 | -------------------------------------------------------------------------------- /RMCalendar/MJExtension/NSObject+MJKeyValue.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+MJKeyValue.h 3 | // MJExtension 4 | // 5 | // Created by mj on 13-8-24. 6 | // Copyright (c) 2013年 小码哥. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MJConst.h" 11 | #import 12 | #import "MJProperty.h" 13 | 14 | /** 15 | * KeyValue协议 16 | */ 17 | @protocol MJKeyValue 18 | @optional 19 | /** 20 | * 只有这个数组中的属性名才允许进行字典和模型的转换 21 | */ 22 | + (NSArray *)allowedPropertyNames; 23 | 24 | /** 25 | * 这个数组中的属性名将会被忽略:不进行字典和模型的转换 26 | */ 27 | + (NSArray *)ignoredPropertyNames; 28 | 29 | /** 30 | * 将属性名换为其他key去字典中取值 31 | * 32 | * @return 字典中的key是属性名,value是从字典中取值用的key 33 | */ 34 | + (NSDictionary *)replacedKeyFromPropertyName; 35 | 36 | /** 37 | * 将属性名换为其他key去字典中取值 38 | * 39 | * @return 从字典中取值用的key 40 | */ 41 | + (NSString *)replacedKeyFromPropertyName121:(NSString *)propertyName; 42 | 43 | /** 44 | * 数组中需要转换的模型类 45 | * 46 | * @return 字典中的key是数组属性名,value是数组中存放模型的Class(Class类型或者NSString类型) 47 | */ 48 | + (NSDictionary *)objectClassInArray; 49 | 50 | /** 51 | * 旧值换新值,用于过滤字典中的值 52 | * 53 | * @param oldValue 旧值 54 | * 55 | * @return 新值 56 | */ 57 | - (id)newValueFromOldValue:(id)oldValue property:(MJProperty *)property; 58 | 59 | /** 60 | * 当字典转模型完毕时调用 61 | */ 62 | - (void)keyValuesDidFinishConvertingToObject; 63 | 64 | /** 65 | * 当模型转字典完毕时调用 66 | */ 67 | - (void)objectDidFinishConvertingToKeyValues; 68 | @end 69 | 70 | @interface NSObject (MJKeyValue) 71 | /** 72 | * 将字典的键值对转成模型属性 73 | * @param keyValues 字典 74 | */ 75 | - (instancetype)setKeyValues:(id)keyValues; 76 | - (instancetype)setKeyValues:(id)keyValues error:(NSError **)error; 77 | 78 | /** 79 | * 将字典的键值对转成模型属性 80 | * @param keyValues 字典 81 | * @param context CoreData上下文 82 | */ 83 | - (instancetype)setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context; 84 | - (instancetype)setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context error:(NSError **)error; 85 | 86 | /** 87 | * 将模型转成字典 88 | * @return 字典 89 | */ 90 | - (NSMutableDictionary *)keyValues; 91 | - (NSMutableDictionary *)keyValuesWithKeys:(NSArray *)keys; 92 | - (NSMutableDictionary *)keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys; 93 | - (NSMutableDictionary *)keyValuesWithError:(NSError **)error; 94 | - (NSMutableDictionary *)keyValuesWithKeys:(NSArray *)keys error:(NSError **)error; 95 | - (NSMutableDictionary *)keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys error:(NSError **)error; 96 | 97 | /** 98 | * 通过模型数组来创建一个字典数组 99 | * @param objectArray 模型数组 100 | * @return 字典数组 101 | */ 102 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray; 103 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys; 104 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys; 105 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray error:(NSError **)error; 106 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys error:(NSError **)error; 107 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys error:(NSError **)error; 108 | 109 | #pragma mark - 字典转模型 110 | /** 111 | * 通过字典来创建一个模型 112 | * @param keyValues 字典(可以是NSDictionary、NSData、NSString) 113 | * @return 新建的对象 114 | */ 115 | + (instancetype)objectWithKeyValues:(id)keyValues; 116 | + (instancetype)objectWithKeyValues:(id)keyValues error:(NSError **)error; 117 | 118 | /** 119 | * 通过字典来创建一个CoreData模型 120 | * @param keyValues 字典(可以是NSDictionary、NSData、NSString) 121 | * @param context CoreData上下文 122 | * @return 新建的对象 123 | */ 124 | + (instancetype)objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context; 125 | + (instancetype)objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context error:(NSError **)error; 126 | 127 | /** 128 | * 通过plist来创建一个模型 129 | * @param filename 文件名(仅限于mainBundle中的文件) 130 | * @return 新建的对象 131 | */ 132 | + (instancetype)objectWithFilename:(NSString *)filename; 133 | + (instancetype)objectWithFilename:(NSString *)filename error:(NSError **)error; 134 | 135 | /** 136 | * 通过plist来创建一个模型 137 | * @param file 文件全路径 138 | * @return 新建的对象 139 | */ 140 | + (instancetype)objectWithFile:(NSString *)file; 141 | + (instancetype)objectWithFile:(NSString *)file error:(NSError **)error; 142 | 143 | #pragma mark - 字典数组转模型数组 144 | /** 145 | * 通过字典数组来创建一个模型数组 146 | * @param keyValuesArray 字典数组(可以是NSDictionary、NSData、NSString) 147 | * @return 模型数组 148 | */ 149 | + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray; 150 | + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray error:(NSError **)error; 151 | 152 | /** 153 | * 通过字典数组来创建一个模型数组 154 | * @param keyValuesArray 字典数组(可以是NSDictionary、NSData、NSString) 155 | * @param context CoreData上下文 156 | * @return 模型数组 157 | */ 158 | + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context; 159 | + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context error:(NSError **)error; 160 | 161 | /** 162 | * 通过plist来创建一个模型数组 163 | * @param filename 文件名(仅限于mainBundle中的文件) 164 | * @return 模型数组 165 | */ 166 | + (NSMutableArray *)objectArrayWithFilename:(NSString *)filename; 167 | + (NSMutableArray *)objectArrayWithFilename:(NSString *)filename error:(NSError **)error; 168 | 169 | /** 170 | * 通过plist来创建一个模型数组 171 | * @param file 文件全路径 172 | * @return 模型数组 173 | */ 174 | + (NSMutableArray *)objectArrayWithFile:(NSString *)file; 175 | + (NSMutableArray *)objectArrayWithFile:(NSString *)file error:(NSError **)error; 176 | 177 | #pragma mark - 转换为JSON 178 | - (NSData *)JSONData; 179 | - (id)JSONObject; 180 | - (NSString *)JSONString; 181 | @end 182 | -------------------------------------------------------------------------------- /RMCalendar/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 31 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /Class/View/RMCollectionCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMCollectionCell.m 3 | // RMCalendar 4 | // 5 | // Created by 迟浩东 on 15/7/15. 6 | // Copyright © 2015年 迟浩东(http://www.ruanman.net). All rights reserved. 7 | // 8 | 9 | #import "RMCollectionCell.h" 10 | #import "UIView+CustomFrame.h" 11 | #import "RMCalendarModel.h" 12 | 13 | #import "TicketModel.h" 14 | 15 | #define kFont(x) [UIFont systemFontOfSize:x] 16 | #define COLOR_HIGHLIGHT ([UIColor redColor]) 17 | #define COLOR_NOAML ([UIColor colorWithRed:26/256.0 green:168/256.0 blue:186/256.0 alpha:1]) 18 | 19 | @interface RMCollectionCell() 20 | 21 | /** 22 | * 显示日期 23 | */ 24 | @property (nonatomic, weak) UILabel *dayLabel; 25 | /** 26 | * 显示农历 27 | */ 28 | @property (nonatomic, weak) UILabel *chineseCalendar; 29 | /** 30 | * 选中的背景图片 31 | */ 32 | @property (nonatomic, weak) UIImageView *selectImageView; 33 | /** 34 | * 票价 此处可根据项目需求自行修改 35 | */ 36 | @property (nonatomic, weak) UILabel *price; 37 | 38 | 39 | @end 40 | 41 | @implementation RMCollectionCell 42 | 43 | - (nonnull instancetype)initWithFrame:(CGRect)frame { 44 | self = [super initWithFrame:frame]; 45 | if (!self) return nil; 46 | [self initCellView]; 47 | return self; 48 | } 49 | 50 | - (void)initCellView { 51 | 52 | //选中时显示的图片 53 | UIImageView *selectImageView = [[UIImageView alloc]initWithFrame:self.bounds]; 54 | selectImageView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"CalendarSelectedDate"]]; 55 | self.selectImageView = selectImageView; 56 | [self addSubview:selectImageView]; 57 | 58 | UILabel *dayLabel = [[UILabel alloc] initWithFrame:CGRectMake(5, 0, self.bounds.size.width * 0.5, self.bounds.size.width * 0.5)]; 59 | dayLabel.font = kFont(14); 60 | self.dayLabel = dayLabel; 61 | [self addSubview:dayLabel]; 62 | 63 | UILabel *chineseCalendar = [[UILabel alloc] initWithFrame:CGRectMake(self.bounds.size.width * 0.5, 0, dayLabel.width, dayLabel.height)]; 64 | chineseCalendar.font = kFont(9); 65 | chineseCalendar.textAlignment = NSTextAlignmentCenter; 66 | self.chineseCalendar = chineseCalendar; 67 | [self addSubview:chineseCalendar]; 68 | 69 | #warning 价格Label 可根据需求修改 70 | UILabel *price = [[UILabel alloc] initWithFrame:CGRectMake(0, dayLabel.height, self.bounds.size.width, dayLabel.height)]; 71 | price.font = kFont(9); 72 | price.textAlignment = NSTextAlignmentCenter; 73 | self.price = price; 74 | [self addSubview:price]; 75 | } 76 | 77 | - (void)setModel:(RMCalendarModel *)model { 78 | _model = model; 79 | //没有剩余票数 80 | if (!model.ticketModel.ticketCount || model.style == CellDayTypePast) { 81 | self.price.hidden = YES; 82 | model.isEnable ? model.style : model.style != CellDayTypeEmpty ? model.style = CellDayTypePast : model.style; 83 | } else { 84 | self.price.hidden = NO; 85 | self.price.textColor = [UIColor orangeColor]; 86 | self.price.text = [NSString stringWithFormat:@"¥%.1f",model.ticketModel.ticketPrice]; 87 | } 88 | self.chineseCalendar.text = model.Chinese_calendar; 89 | self.chineseCalendar.hidden = NO; 90 | /** 91 | * 如果不展示农历,则日期居中 92 | */ 93 | if (!model.isChineseCalendar) { 94 | self.dayLabel.x = 0; 95 | self.dayLabel.width = self.bounds.size.width; 96 | self.dayLabel.textAlignment = NSTextAlignmentCenter; 97 | } 98 | 99 | switch (model.style) { 100 | case CellDayTypeEmpty: 101 | self.selectImageView.hidden = YES; 102 | self.dayLabel.hidden = YES; 103 | self.backgroundColor = [UIColor whiteColor]; 104 | self.chineseCalendar.hidden = YES; 105 | break; 106 | case CellDayTypePast: 107 | self.dayLabel.hidden = NO; 108 | self.selectImageView.hidden = YES; 109 | if (model.holiday) { 110 | self.dayLabel.text = model.holiday; 111 | self.dayLabel.width = self.bounds.size.width; 112 | self.chineseCalendar.hidden = YES; 113 | } else { 114 | self.dayLabel.text = [NSString stringWithFormat:@"%lu",(unsigned long)model.day]; 115 | } 116 | self.chineseCalendar.textColor = [UIColor lightGrayColor]; 117 | self.dayLabel.textColor = [UIColor lightGrayColor]; 118 | self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"CalendarDisableDate"]]; 119 | break; 120 | 121 | case CellDayTypeWeek: 122 | // 以下内容暂时无用 将来可以设置 周六 日 特殊颜色时 可用 123 | // self.dayLabel.hidden = NO; 124 | // self.selectImageView.hidden = YES; 125 | // if (model.holiday) { 126 | // self.dayLabel.text = model.holiday; 127 | // self.dayLabel.textColor = COLOR_HIGHLIGHT; 128 | // } else { 129 | // self.dayLabel.text = [NSString stringWithFormat:@"%lu",(unsigned long)model.day]; 130 | // self.dayLabel.textColor = COLOR_NOAML; 131 | // } 132 | // self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"CalendarNormalDate"]]; 133 | // self.chineseCalendar.textColor = [UIColor blackColor]; 134 | // break; 135 | 136 | case CellDayTypeFutur: 137 | self.dayLabel.hidden = NO; 138 | self.selectImageView.hidden = YES; 139 | if (model.holiday) { 140 | self.dayLabel.text = model.holiday; 141 | self.dayLabel.width = self.bounds.size.width; 142 | self.chineseCalendar.hidden = YES; 143 | self.dayLabel.textColor = COLOR_HIGHLIGHT; 144 | } else { 145 | self.dayLabel.text = [NSString stringWithFormat:@"%lu",(unsigned long)model.day]; 146 | self.dayLabel.textColor = COLOR_NOAML; 147 | } 148 | self.chineseCalendar.textColor = [UIColor blackColor]; 149 | self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"CalendarNormalDate"]]; 150 | break; 151 | 152 | case CellDayTypeClick: 153 | self.dayLabel.hidden = NO; 154 | self.selectImageView.hidden = NO; 155 | self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"CalendarNormalDate"]]; 156 | self.dayLabel.text = [NSString stringWithFormat:@"%lu",(unsigned long)model.day]; 157 | self.dayLabel.textColor = [UIColor whiteColor]; 158 | self.price.textColor = [UIColor whiteColor]; 159 | self.chineseCalendar.textColor = [UIColor whiteColor]; 160 | break; 161 | 162 | default: 163 | break; 164 | } 165 | 166 | } 167 | 168 | @end 169 | -------------------------------------------------------------------------------- /Class/Controller/RMCalendarController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMCalendarController.m 3 | // RMCalendar 4 | // 5 | // Created by 迟浩东 on 15/7/15. 6 | // Copyright © 2015年 迟浩东(http://www.ruanman.net). All rights reserved. 7 | // 8 | 9 | #import "RMCalendarController.h" 10 | #import "RMCalendarCollectionViewLayout.h" 11 | #import "RMCollectionCell.h" 12 | #import "RMCalendarMonthHeaderView.h" 13 | #import "RMCalendarLogic.h" 14 | 15 | @interface RMCalendarController () 16 | 17 | @end 18 | 19 | @implementation RMCalendarController 20 | 21 | static NSString *MonthHeader = @"MonthHeaderView"; 22 | 23 | static NSString *DayCell = @"DayCell"; 24 | 25 | /** 26 | * 初始化模型数组对象 27 | */ 28 | - (NSMutableArray *)calendarMonth { 29 | if (!_calendarMonth) { 30 | _calendarMonth = [NSMutableArray array]; 31 | } 32 | return _calendarMonth; 33 | } 34 | 35 | - (RMCalendarLogic *)calendarLogic { 36 | if (!_calendarLogic) { 37 | _calendarLogic = [[RMCalendarLogic alloc] init]; 38 | } 39 | return _calendarLogic; 40 | } 41 | 42 | - (instancetype)initWithDays:(int)days showType:(CalendarShowType)type modelArrar:(NSMutableArray *)modelArr { 43 | self = [super init]; 44 | if (!self) return nil; 45 | self.days = days; 46 | self.type = type; 47 | self.modelArr = modelArr; 48 | return self; 49 | } 50 | 51 | - (instancetype)initWithDays:(int)days showType:(CalendarShowType)type { 52 | self = [super init]; 53 | if (!self) return nil; 54 | self.days = days; 55 | self.type = type; 56 | return self; 57 | } 58 | 59 | + (instancetype)calendarWithDays:(int)days showType:(CalendarShowType)type modelArrar:(NSMutableArray *)modelArr { 60 | return [[self alloc] initWithDays:days showType:type modelArrar:modelArr]; 61 | } 62 | 63 | + (instancetype)calendarWithDays:(int)days showType:(CalendarShowType)type { 64 | return [[self alloc] initWithDays:days showType:type]; 65 | } 66 | 67 | - (void)setModelArr:(NSMutableArray *)modelArr { 68 | #if __has_feature(objc_arc) 69 | _modelArr = modelArr; 70 | #else 71 | if (_modelArr != modelArr) { 72 | [_modelArr release]; 73 | _modelArr = [modelArr retain]; 74 | } 75 | #endif 76 | } 77 | 78 | - (void)viewDidLoad { 79 | [super viewDidLoad]; 80 | // 定义Layout对象 81 | RMCalendarCollectionViewLayout *layout = [[RMCalendarCollectionViewLayout alloc] init]; 82 | 83 | // 初始化CollectionView 84 | self.collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout]; 85 | 86 | #if !__has_feature(objc_arc) 87 | [layout release]; 88 | #endif 89 | 90 | // 注册CollectionView的Cell 91 | [self.collectionView registerClass:[RMCollectionCell class] forCellWithReuseIdentifier:DayCell]; 92 | 93 | [self.collectionView registerClass:[RMCalendarMonthHeaderView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:MonthHeader]; 94 | 95 | // self.collectionView.bounces = NO;//将网格视图的下拉效果关闭 96 | 97 | self.collectionView.delegate = self;//实现网格视图的delegate 98 | 99 | self.collectionView.dataSource = self;//实现网格视图的dataSource 100 | 101 | self.collectionView.backgroundColor = [UIColor whiteColor]; 102 | 103 | [self.view addSubview:self.collectionView]; 104 | 105 | self.calendarMonth = [self getMonthArrayOfDays:self.days showType:self.type isEnable:self.isEnable modelArr:self.modelArr]; 106 | } 107 | 108 | - (void)didReceiveMemoryWarning { 109 | [super didReceiveMemoryWarning]; 110 | } 111 | 112 | /** 113 | * 获取Days天数内的数组 114 | * 115 | * @param days 天数 116 | * @param type 显示类型 117 | * @param arr 模型数组 118 | * @return 数组 119 | */ 120 | - (NSMutableArray *)getMonthArrayOfDays:(int)days showType:(CalendarShowType)type isEnable:(BOOL)isEnable modelArr:(NSArray *)arr 121 | { 122 | NSDate *date = [NSDate date]; 123 | 124 | NSDate *selectdate = [NSDate date]; 125 | //返回数据模型数组 126 | return [self.calendarLogic reloadCalendarView:date selectDate:selectdate needDays:days showType:type isEnable:isEnable priceModelArr:arr isChineseCalendar:self.isDisplayChineseCalendar]; 127 | } 128 | 129 | #pragma mark - CollectionView 数据源 130 | 131 | // 返回组数 132 | - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { 133 | return self.calendarMonth.count; 134 | } 135 | // 返回每组行数 136 | - (NSInteger)collectionView:(nonnull UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 137 | NSArray *arrary = [self.calendarMonth objectAtIndex:section]; 138 | return arrary.count; 139 | } 140 | 141 | #pragma mark - CollectionView 代理 142 | 143 | - (UICollectionViewCell *)collectionView:(nonnull UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath { 144 | RMCollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:DayCell forIndexPath:indexPath]; 145 | NSArray *months = [self.calendarMonth objectAtIndex:indexPath.section]; 146 | RMCalendarModel *model = [months objectAtIndex:indexPath.row]; 147 | cell.model = model; 148 | return cell; 149 | } 150 | 151 | - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath 152 | { 153 | UICollectionReusableView *reusableview = nil; 154 | 155 | if (kind == UICollectionElementKindSectionHeader){ 156 | 157 | NSMutableArray *month_Array = [self.calendarMonth objectAtIndex:indexPath.section]; 158 | RMCalendarModel *model = [month_Array objectAtIndex:15]; 159 | 160 | RMCalendarMonthHeaderView *monthHeader = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:MonthHeader forIndexPath:indexPath]; 161 | monthHeader.masterLabel.text = [NSString stringWithFormat:@"%lu年 %lu月",(unsigned long)model.year,(unsigned long)model.month];//@"日期"; 162 | monthHeader.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.8f]; 163 | reusableview = monthHeader; 164 | } 165 | return reusableview; 166 | 167 | } 168 | 169 | - (void)collectionView:(nonnull UICollectionView *)collectionView didSelectItemAtIndexPath:(nonnull NSIndexPath *)indexPath { 170 | NSArray *months = [self.calendarMonth objectAtIndex:indexPath.section]; 171 | RMCalendarModel *model = [months objectAtIndex:indexPath.row]; 172 | if (model.style == CellDayTypeClick || model.style == CellDayTypeFutur || model.style == CellDayTypeWeek) { 173 | [self.calendarLogic selectLogic:model]; 174 | if (self.calendarBlock) { 175 | self.calendarBlock(model); 176 | } 177 | } 178 | [self.collectionView reloadData]; 179 | } 180 | 181 | - (BOOL)collectionView:(nonnull UICollectionView *)collectionView shouldSelectItemAtIndexPath:(nonnull NSIndexPath *)indexPath { 182 | return YES; 183 | } 184 | 185 | -(void)dealloc { 186 | #if !__has_feature(objc_arc) 187 | [self.collectionView release]; 188 | [super dealloc]; 189 | #endif 190 | } 191 | 192 | 193 | @end 194 | -------------------------------------------------------------------------------- /Class/Category/NSDate+RMCalendarLogic.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate+RMCalendarLogic.m 3 | // RMCalendar 4 | // 5 | // Created by 迟浩东 on 15/7/15. 6 | // Copyright © 2015年 迟浩东(http://www.ruanman.net). All rights reserved. 7 | // 8 | 9 | #import "NSDate+RMCalendarLogic.h" 10 | 11 | @implementation NSDate (RMCalendarLogic) 12 | 13 | /*计算这个月有多少天*/ 14 | - (NSUInteger)numberOfDaysInCurrentMonth 15 | { 16 | // 频繁调用 [NSCalendar currentCalendar] 可能存在性能问题 17 | return [[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit inUnit:NSMonthCalendarUnit forDate:self].length; 18 | } 19 | 20 | 21 | //获取这个月有多少周 22 | - (NSUInteger)numberOfWeeksInCurrentMonth 23 | { 24 | NSUInteger weekday = [[self firstDayOfCurrentMonth] weeklyOrdinality]; 25 | NSUInteger days = [self numberOfDaysInCurrentMonth]; 26 | NSUInteger weeks = 0; 27 | 28 | if (weekday > 1) { 29 | weeks += 1, days -= (7 - weekday + 1); 30 | } 31 | 32 | weeks += days / 7; 33 | weeks += (days % 7 > 0) ? 1 : 0; 34 | 35 | return weeks; 36 | } 37 | 38 | 39 | 40 | /*计算这个月的第一天是礼拜几*/ 41 | - (NSUInteger)weeklyOrdinality 42 | { 43 | return [[NSCalendar currentCalendar] ordinalityOfUnit:NSDayCalendarUnit inUnit:NSWeekCalendarUnit forDate:self]; 44 | } 45 | 46 | 47 | 48 | //计算这个月最开始的一天 49 | - (NSDate *)firstDayOfCurrentMonth 50 | { 51 | NSDate *startDate = nil; 52 | BOOL ok = [[NSCalendar currentCalendar] rangeOfUnit:NSMonthCalendarUnit startDate:&startDate interval:NULL forDate:self]; 53 | NSAssert1(ok, @"Failed to calculate the first day of the month based on %@", self); 54 | return startDate; 55 | } 56 | 57 | 58 | - (NSDate *)lastDayOfCurrentMonth 59 | { 60 | NSCalendarUnit calendarUnit = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit; 61 | NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:calendarUnit fromDate:self]; 62 | dateComponents.day = [self numberOfDaysInCurrentMonth]; 63 | return [[NSCalendar currentCalendar] dateFromComponents:dateComponents]; 64 | } 65 | 66 | //上一个月 67 | - (NSDate *)dayInThePreviousMonth 68 | { 69 | NSDateComponents *dateComponents = [[NSDateComponents alloc] init]; 70 | dateComponents.month = -1; 71 | return [[NSCalendar currentCalendar] dateByAddingComponents:dateComponents toDate:self options:0]; 72 | } 73 | 74 | //下一个月 75 | - (NSDate *)dayInTheFollowingMonth 76 | { 77 | NSDateComponents *dateComponents = [[NSDateComponents alloc] init]; 78 | dateComponents.month = 1; 79 | return [[NSCalendar currentCalendar] dateByAddingComponents:dateComponents toDate:self options:0]; 80 | } 81 | 82 | 83 | //获取当前日期之后的几个月 84 | - (NSDate *)dayInTheFollowingMonth:(int)month 85 | { 86 | NSDateComponents *dateComponents = [[NSDateComponents alloc] init]; 87 | dateComponents.month = month; 88 | return [[NSCalendar currentCalendar] dateByAddingComponents:dateComponents toDate:self options:0]; 89 | } 90 | 91 | //获取当前日期之后的几个天 92 | - (NSDate *)dayInTheFollowingDay:(int)day 93 | { 94 | NSDateComponents *dateComponents = [[NSDateComponents alloc] init]; 95 | dateComponents.day = day; 96 | return [[NSCalendar currentCalendar] dateByAddingComponents:dateComponents toDate:self options:0]; 97 | } 98 | 99 | //获取年月日对象 100 | - (NSDateComponents *)YMDComponents 101 | { 102 | return [[NSCalendar currentCalendar] components: 103 | NSYearCalendarUnit| 104 | NSMonthCalendarUnit| 105 | NSDayCalendarUnit| 106 | NSWeekdayCalendarUnit fromDate:self]; 107 | } 108 | 109 | 110 | //----------------------------------------- 111 | // 112 | //NSString转NSDate 113 | - (NSDate *)dateFromString:(NSString *)dateString 114 | { 115 | 116 | NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 117 | 118 | // [dateFormatter setDateFormat: @"yyyy-MM-dd HH:mm:ss"]; 119 | [dateFormatter setDateFormat: @"yyyy-MM-dd"]; 120 | 121 | NSDate *destDate= [dateFormatter dateFromString:dateString]; 122 | 123 | return destDate; 124 | 125 | } 126 | 127 | 128 | 129 | //NSDate转NSString 130 | - (NSString *)stringFromDate:(NSDate *)date 131 | { 132 | NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 133 | 134 | //zzz表示时区,zzz可以删除,这样返回的日期字符将不包含时区信息。 135 | 136 | // [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss zzz"]; 137 | [dateFormatter setDateFormat:@"yyyy-MM-dd"]; 138 | 139 | NSString *destDateString = [dateFormatter stringFromDate:date]; 140 | 141 | return destDateString; 142 | } 143 | 144 | 145 | + (int)getDayNumbertoDay:(NSDate *)today beforDay:(NSDate *)beforday 146 | { 147 | 148 | NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];//日历控件对象 149 | NSDateComponents *components = [calendar components:NSDayCalendarUnit fromDate:today toDate:beforday options:0]; 150 | // NSDateComponents *components = [calendar components:NSMonthCalendarUnit|NSDayCalendarUnit fromDate:today toDate:beforday options:0]; 151 | int day = (int)[components day];//两个日历之间相差多少月// NSInteger days = [components day];//两个之间相差几天 152 | return day; 153 | } 154 | 155 | 156 | //周日是“1”,周一是“2”... 157 | - (int)getWeekIntValueWithDate 158 | { 159 | int weekIntValue; 160 | 161 | NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSChineseCalendar]; 162 | NSDateComponents *comps= [calendar components:(NSYearCalendarUnit | 163 | NSMonthCalendarUnit | 164 | NSDayCalendarUnit | 165 | NSWeekdayCalendarUnit) fromDate:self]; 166 | return weekIntValue = (int)[comps weekday]; 167 | } 168 | 169 | 170 | 171 | 172 | //判断日期是今天,明天,后天,周几 173 | -(NSString *)compareIfTodayWithDate 174 | { 175 | NSDate *todate = [NSDate date];//今天 176 | NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSChineseCalendar]; 177 | NSDateComponents *comps_today= [calendar components:(NSYearCalendarUnit | 178 | NSMonthCalendarUnit | 179 | NSDayCalendarUnit | 180 | NSWeekdayCalendarUnit) fromDate:todate]; 181 | 182 | 183 | NSDateComponents *comps_other= [calendar components:(NSYearCalendarUnit | 184 | NSMonthCalendarUnit | 185 | NSDayCalendarUnit | 186 | NSWeekdayCalendarUnit) fromDate:self]; 187 | 188 | 189 | //获取星期对应的数字 190 | int weekIntValue = [self getWeekIntValueWithDate]; 191 | 192 | if (comps_today.year == comps_other.year && 193 | comps_today.month == comps_other.month && 194 | comps_today.day == comps_other.day) { 195 | return @"今天"; 196 | 197 | }else if (comps_today.year == comps_other.year && 198 | comps_today.month == comps_other.month && 199 | (comps_today.day - comps_other.day) == -1){ 200 | return @"明天"; 201 | 202 | }else if (comps_today.year == comps_other.year && 203 | comps_today.month == comps_other.month && 204 | (comps_today.day - comps_other.day) == -2){ 205 | return @"后天"; 206 | 207 | }else{ 208 | //直接返回当时日期的字符串(这里让它返回空) 209 | return [NSDate getWeekStringFromInteger:weekIntValue];//周几 210 | } 211 | } 212 | 213 | 214 | 215 | //通过数字返回星期几 216 | +(NSString *)getWeekStringFromInteger:(int)week 217 | { 218 | NSString *str_week; 219 | 220 | switch (week) { 221 | case 1: 222 | str_week = @"周日"; 223 | break; 224 | case 2: 225 | str_week = @"周一"; 226 | break; 227 | case 3: 228 | str_week = @"周二"; 229 | break; 230 | case 4: 231 | str_week = @"周三"; 232 | break; 233 | case 5: 234 | str_week = @"周四"; 235 | break; 236 | case 6: 237 | str_week = @"周五"; 238 | break; 239 | case 7: 240 | str_week = @"周六"; 241 | break; 242 | } 243 | return str_week; 244 | } 245 | 246 | 247 | @end 248 | -------------------------------------------------------------------------------- /RMCalendar/MJExtension/NSObject+MJProperty.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+MJProperty.m 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 15/4/17. 6 | // Copyright (c) 2015年 小码哥. All rights reserved. 7 | // 8 | 9 | #import "NSObject+MJProperty.h" 10 | #import "NSObject+MJKeyValue.h" 11 | #import "NSObject+MJCoding.h" 12 | #import "MJProperty.h" 13 | #import "MJFoundation.h" 14 | #import 15 | 16 | static const char MJReplacedKeyFromPropertyNameKey = '\0'; 17 | static const char MJReplacedKeyFromPropertyName121Key = '\0'; 18 | static const char MJNewValueFromOldValueKey = '\0'; 19 | static const char MJObjectClassInArrayKey = '\0'; 20 | static const char MJAllowedPropertyNamesKey = '\0'; 21 | static const char MJAllowedCodingPropertyNamesKey = '\0'; 22 | static const char MJIgnoredPropertyNamesKey = '\0'; 23 | static const char MJIgnoredCodingPropertyNamesKey = '\0'; 24 | 25 | @implementation NSObject (Property) 26 | #pragma mark - --私有方法-- 27 | + (NSString *)propertyKey:(NSString *)propertyName 28 | { 29 | MJAssertParamNotNil2(propertyName, nil); 30 | 31 | __block NSString *key = nil; 32 | // 查看有没有需要替换的key 33 | if ([self respondsToSelector:@selector(replacedKeyFromPropertyName121:)]) { 34 | key = [self replacedKeyFromPropertyName121:propertyName]; 35 | } 36 | 37 | // 调用block 38 | if (!key) { 39 | [self enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) { 40 | MJReplacedKeyFromPropertyName121 block = objc_getAssociatedObject(c, &MJReplacedKeyFromPropertyName121Key); 41 | if (block) { 42 | key = block(propertyName); 43 | } 44 | if (key) *stop = YES; 45 | }]; 46 | } 47 | 48 | // 查看有没有需要替换的key 49 | if (!key && [self respondsToSelector:@selector(replacedKeyFromPropertyName)]) { 50 | key = [self replacedKeyFromPropertyName][propertyName]; 51 | } 52 | 53 | if (!key) { 54 | [self enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) { 55 | NSDictionary *dict = objc_getAssociatedObject(c, &MJReplacedKeyFromPropertyNameKey); 56 | if (dict) { 57 | key = dict[propertyName]; 58 | } 59 | if (key) *stop = YES; 60 | }]; 61 | } 62 | 63 | // 2.用属性名作为key 64 | if (!key) key = propertyName; 65 | 66 | return key; 67 | } 68 | 69 | + (Class)propertyObjectClassInArray:(NSString *)propertyName 70 | { 71 | __block id aClass = nil; 72 | if ([self respondsToSelector:@selector(objectClassInArray)]) { 73 | aClass = [self objectClassInArray][propertyName]; 74 | } 75 | 76 | if (!aClass) { 77 | [self enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) { 78 | NSDictionary *dict = objc_getAssociatedObject(c, &MJObjectClassInArrayKey); 79 | if (dict) { 80 | aClass = dict[propertyName]; 81 | } 82 | if (aClass) *stop = YES; 83 | }]; 84 | } 85 | 86 | // 如果是NSString类型 87 | if ([aClass isKindOfClass:[NSString class]]) { 88 | aClass = NSClassFromString(aClass); 89 | } 90 | return aClass; 91 | } 92 | 93 | #pragma mark - --公共方法-- 94 | + (void)enumerateProperties:(MJPropertiesEnumeration)enumeration 95 | { 96 | // 获得成员变量 97 | NSArray *cachedProperties = [self properties]; 98 | 99 | // 遍历成员变量 100 | BOOL stop = NO; 101 | for (MJProperty *property in cachedProperties) { 102 | enumeration(property, &stop); 103 | if (stop) break; 104 | } 105 | } 106 | 107 | + (void)enumerateClasses:(MJClassesEnumeration)enumeration 108 | { 109 | // 1.没有block就直接返回 110 | if (enumeration == nil) return; 111 | 112 | // 2.停止遍历的标记 113 | BOOL stop = NO; 114 | 115 | // 3.当前正在遍历的类 116 | Class c = self; 117 | 118 | // 4.开始遍历每一个类 119 | while (c && !stop) { 120 | // 4.1.执行操作 121 | enumeration(c, &stop); 122 | 123 | // 4.2.获得父类 124 | c = class_getSuperclass(c); 125 | 126 | if ([MJFoundation isClassFromFoundation:c]) break; 127 | } 128 | } 129 | 130 | + (void)enumerateAllClasses:(MJClassesEnumeration)enumeration 131 | { 132 | // 1.没有block就直接返回 133 | if (enumeration == nil) return; 134 | 135 | // 2.停止遍历的标记 136 | BOOL stop = NO; 137 | 138 | // 3.当前正在遍历的类 139 | Class c = self; 140 | 141 | // 4.开始遍历每一个类 142 | while (c && !stop) { 143 | // 4.1.执行操作 144 | enumeration(c, &stop); 145 | 146 | // 4.2.获得父类 147 | c = class_getSuperclass(c); 148 | } 149 | } 150 | 151 | #pragma mark - 公共方法 152 | + (NSMutableArray *)properties 153 | { 154 | static const char MJCachedPropertiesKey = '\0'; 155 | 156 | // 获得成员变量 157 | // 通过关联对象,以及提前定义好的MJCachedPropertiesKey来进行运行时,对所有属性的获取。 158 | 159 | //***objc_getAssociatedObject 方法用于判断当前是否已经获取过MJCachedPropertiesKey对应的关联对象 160 | // 1> 关联到的对象 161 | // 2> 关联的属性 key 162 | NSMutableArray *cachedProperties = objc_getAssociatedObject(self, &MJCachedPropertiesKey); 163 | //*** 164 | if (cachedProperties == nil) { 165 | cachedProperties = [NSMutableArray array]; 166 | 167 | /**遍历这个类的父类*/ 168 | [self enumerateClasses:^(__unsafe_unretained Class c, BOOL *stop) { 169 | // 1.获得所有的成员变量 170 | unsigned int outCount = 0; 171 | /** 172 | class_copyIvarList 成员变量,提示有很多第三方框架会使用 Ivar,能够获得更多的信息 173 | 但是:在 swift 中,由于语法结构的变化,使用 Ivar 非常不稳定,经常会崩溃! 174 | class_copyPropertyList 属性 175 | class_copyMethodList 方法 176 | class_copyProtocolList 协议 177 | */ 178 | objc_property_t *properties = class_copyPropertyList(c, &outCount); 179 | 180 | // 2.遍历每一个成员变量 181 | for (unsigned int i = 0; i 模型 27 | + (instancetype)objectWithKeyValues:(id)keyValues 28 | { 29 | return [self objectWithKeyValues:keyValues error:nil]; 30 | } 31 | 32 | + (instancetype)objectWithKeyValues:(id)keyValues error:(NSError *__autoreleasing *)error 33 | { 34 | return [self objectWithKeyValues:keyValues context:nil error:error]; 35 | } 36 | 37 | + (instancetype)objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context 38 | { 39 | return [self objectWithKeyValues:keyValues context:context error:nil]; 40 | } 41 | 42 | + (instancetype)objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context error:(NSError *__autoreleasing *)error 43 | { 44 | if (keyValues == nil) return nil; 45 | if ([self isSubclassOfClass:[NSManagedObject class]] && context) { 46 | return [[NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass(self) inManagedObjectContext:context] setKeyValues:keyValues context:context error:error]; 47 | } 48 | return [[[self alloc] init] setKeyValues:keyValues error:error]; 49 | } 50 | 51 | + (instancetype)objectWithFilename:(NSString *)filename 52 | { 53 | return [self objectWithFilename:filename error:nil]; 54 | } 55 | 56 | + (instancetype)objectWithFilename:(NSString *)filename error:(NSError *__autoreleasing *)error 57 | { 58 | MJAssertError(filename != nil, nil, error, @"filename参数为nil"); 59 | 60 | return [self objectWithFile:[[NSBundle mainBundle] pathForResource:filename ofType:nil] error:error]; 61 | } 62 | 63 | + (instancetype)objectWithFile:(NSString *)file 64 | { 65 | return [self objectWithFile:file error:nil]; 66 | } 67 | 68 | + (instancetype)objectWithFile:(NSString *)file error:(NSError *__autoreleasing *)error 69 | { 70 | MJAssertError(file != nil, nil, error, @"file参数为nil"); 71 | 72 | return [self objectWithKeyValues:[NSDictionary dictionaryWithContentsOfFile:file] error:error]; 73 | } 74 | 75 | - (instancetype)setKeyValues:(id)keyValues 76 | { 77 | return [self setKeyValues:keyValues error:nil]; 78 | } 79 | 80 | - (instancetype)setKeyValues:(id)keyValues error:(NSError *__autoreleasing *)error 81 | { 82 | return [self setKeyValues:keyValues context:nil error:error]; 83 | } 84 | 85 | - (instancetype)setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context 86 | { 87 | return [self setKeyValues:keyValues context:context error:nil]; 88 | } 89 | 90 | /** 91 | 核心代码: 92 | */ 93 | - (instancetype)setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context error:(NSError *__autoreleasing *)error 94 | { 95 | // 如果是JSON字符串 96 | if ([keyValues isKindOfClass:[NSString class]]) { 97 | keyValues = [((NSString *)keyValues) JSONObject]; 98 | } else if ([keyValues isKindOfClass:[NSData class]]) { 99 | keyValues = [NSJSONSerialization JSONObjectWithData:keyValues options:kNilOptions error:nil]; 100 | } 101 | 102 | MJAssertError([keyValues isKindOfClass:[NSDictionary class]], self, error, @"keyValues参数不是一个字典"); 103 | 104 | @try { 105 | Class aClass = [self class]; 106 | NSArray *allowedPropertyNames = [aClass totalAllowedPropertyNames]; 107 | NSArray *ignoredPropertyNames = [aClass totalIgnoredPropertyNames]; 108 | 109 | //通过封装的方法回调一个通过运行时编写的,用于返回属性列表的方法。 110 | [aClass enumerateProperties:^(MJProperty *property, BOOL *stop) { 111 | // 0.检测是否被忽略 112 | if (allowedPropertyNames.count && ![allowedPropertyNames containsObject:property.name]) return; 113 | if ([ignoredPropertyNames containsObject:property.name]) return; 114 | 115 | // 1.取出属性值 116 | id value = keyValues ; 117 | NSArray *keys = [property keysFromClass:[self class]]; 118 | for (NSString *key in keys) { 119 | if (![value isKindOfClass:[NSDictionary class]]) continue; 120 | value = value[key]; 121 | } 122 | 123 | // 值的过滤 124 | if ([self respondsToSelector:@selector(newValueFromOldValue:property:)]) { 125 | value = [self newValueFromOldValue:value property:property]; 126 | } else { 127 | id newValue = [aClass getNewValueFormOldValue:value object:self property:property]; 128 | if (newValue) value = newValue; 129 | } 130 | 131 | if (!value || value == [NSNull null]) return; 132 | 133 | // 2.如果是模型属性 134 | MJType *type = property.type; 135 | Class typeClass = type.typeClass; 136 | Class objectClass = [property objectClassInArrayFromClass:[self class]]; 137 | if (!type.isFromFoundation && typeClass) { 138 | value = [typeClass objectWithKeyValues:value context:context error:error]; 139 | } else if (objectClass) { 140 | // 3.字典数组-->模型数组 141 | value = [objectClass objectArrayWithKeyValuesArray:value context:context error:error]; 142 | } else if (typeClass == [NSString class]) { 143 | if ([value isKindOfClass:[NSNumber class]]) { 144 | // NSNumber -> NSString 145 | value = [value description]; 146 | } else if ([value isKindOfClass:[NSURL class]]) { 147 | // NSURL -> NSString 148 | value = [value absoluteString]; 149 | } 150 | } else if ([value isKindOfClass:[NSString class]]) { 151 | if (typeClass == [NSURL class]) { 152 | // NSString -> NSURL 153 | // 字符串转码 154 | value = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)value,(CFStringRef)@"!$&'()*+,-./:;=?@_~%#[]", NULL,kCFStringEncodingUTF8)); 155 | value = [NSURL URLWithString:value]; 156 | } else if (type.isNumberType) { 157 | NSString *oldValue = value; 158 | 159 | // NSString -> NSNumber 160 | value = [_numberFormatter numberFromString:oldValue]; 161 | 162 | // 如果是BOOL 163 | if ([type.code isEqualToString:MJTypeBOOL]) { 164 | // 字符串转BOOL(字符串没有charValue方法) 165 | // 系统会调用字符串的charValue转为BOOL类型 166 | NSString *lower = [oldValue lowercaseString]; 167 | if ([lower isEqualToString:@"yes"] || [lower isEqualToString:@"true"]) { 168 | value = @YES; 169 | } else if ([lower isEqualToString:@"no"] || [lower isEqualToString:@"false"]) { 170 | value = @NO; 171 | } 172 | } 173 | } 174 | } 175 | 176 | // 4.赋值 177 | [property setValue:value forObject:self]; 178 | }]; 179 | 180 | // 转换完毕 181 | if ([self respondsToSelector:@selector(keyValuesDidFinishConvertingToObject)]) { 182 | [self keyValuesDidFinishConvertingToObject]; 183 | } 184 | } @catch (NSException *exception) { 185 | MJBuildError(error, exception.reason); 186 | } 187 | return self; 188 | } 189 | 190 | #pragma mark - 字典数组 -> 模型数组 191 | + (NSMutableArray *)objectArrayWithKeyValuesArray:(NSArray *)keyValuesArray 192 | { 193 | return [self objectArrayWithKeyValuesArray:keyValuesArray error:nil]; 194 | } 195 | 196 | + (NSMutableArray *)objectArrayWithKeyValuesArray:(NSArray *)keyValuesArray error:(NSError *__autoreleasing *)error 197 | { 198 | return [self objectArrayWithKeyValuesArray:keyValuesArray context:nil error:error]; 199 | } 200 | 201 | + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context 202 | { 203 | return [self objectArrayWithKeyValuesArray:keyValuesArray context:context error:nil]; 204 | } 205 | 206 | + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context error:(NSError *__autoreleasing *)error 207 | { 208 | // 如果是JSON字符串 209 | if ([keyValuesArray isKindOfClass:[NSString class]]) { 210 | keyValuesArray = [((NSString *)keyValuesArray) JSONObject]; 211 | } else if ([keyValuesArray isKindOfClass:[NSData class]]) { 212 | keyValuesArray = [NSJSONSerialization JSONObjectWithData:keyValuesArray options:kNilOptions error:nil]; 213 | } 214 | 215 | // 如果数组里面放的是NSString、NSNumber等数据 216 | if ([MJFoundation isClassFromFoundation:self]) return keyValuesArray; 217 | 218 | // 1.判断真实性 219 | MJAssertError([keyValuesArray isKindOfClass:[NSArray class]], nil, error, @"keyValuesArray参数不是一个数组"); 220 | 221 | // 2.创建数组 222 | NSMutableArray *modelArray = [NSMutableArray array]; 223 | 224 | // 3.遍历 225 | for (NSDictionary *keyValues in keyValuesArray) { 226 | if ([keyValues isKindOfClass:[NSArray class]]){ 227 | [modelArray addObject:[self objectArrayWithKeyValuesArray:keyValues context:context error:error]]; 228 | } else { 229 | id model = [self objectWithKeyValues:keyValues context:context error:error]; 230 | if (model) [modelArray addObject:model]; 231 | } 232 | } 233 | 234 | return modelArray; 235 | } 236 | 237 | + (NSMutableArray *)objectArrayWithFilename:(NSString *)filename 238 | { 239 | return [self objectArrayWithFilename:filename error:nil]; 240 | } 241 | 242 | + (NSMutableArray *)objectArrayWithFilename:(NSString *)filename error:(NSError *__autoreleasing *)error 243 | { 244 | MJAssertError(filename != nil, nil, error, @"filename参数为nil"); 245 | 246 | return [self objectArrayWithFile:[[NSBundle mainBundle] pathForResource:filename ofType:nil] error:error]; 247 | } 248 | 249 | + (NSMutableArray *)objectArrayWithFile:(NSString *)file 250 | { 251 | return [self objectArrayWithFile:file error:nil]; 252 | } 253 | 254 | + (NSMutableArray *)objectArrayWithFile:(NSString *)file error:(NSError *__autoreleasing *)error 255 | { 256 | MJAssertError(file != nil, nil, error, @"file参数为nil"); 257 | 258 | return [self objectArrayWithKeyValuesArray:[NSArray arrayWithContentsOfFile:file] error:error]; 259 | } 260 | 261 | #pragma mark - 模型 -> 字典 262 | - (NSMutableDictionary *)keyValues 263 | { 264 | return [self keyValuesWithError:nil]; 265 | } 266 | 267 | - (NSMutableDictionary *)keyValuesWithError:(NSError *__autoreleasing *)error 268 | { 269 | return [self keyValuesWithIgnoredKeys:nil error:error]; 270 | } 271 | 272 | - (NSMutableDictionary *)keyValuesWithKeys:(NSArray *)keys 273 | { 274 | return [self keyValuesWithKeys:keys error:nil]; 275 | } 276 | 277 | - (NSMutableDictionary *)keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys 278 | { 279 | return [self keyValuesWithIgnoredKeys:ignoredKeys error:nil]; 280 | } 281 | 282 | - (NSMutableDictionary *)keyValuesWithKeys:(NSArray *)keys error:(NSError *__autoreleasing *)error 283 | { 284 | return [self keyValuesWithKeys:keys ignoredKeys:nil error:error]; 285 | } 286 | 287 | - (NSMutableDictionary *)keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys error:(NSError *__autoreleasing *)error 288 | { 289 | return [self keyValuesWithKeys:nil ignoredKeys:ignoredKeys error:error]; 290 | } 291 | 292 | - (NSMutableDictionary *)keyValuesWithKeys:(NSArray *)keys ignoredKeys:(NSArray *)ignoredKeys error:(NSError *__autoreleasing *)error 293 | { 294 | // 如果自己不是模型类 295 | if ([MJFoundation isClassFromFoundation:[self class]]) return (NSMutableDictionary *)self; 296 | 297 | __block NSMutableDictionary *keyValues = [NSMutableDictionary dictionary]; 298 | 299 | @try { 300 | Class aClass = [self class]; 301 | NSArray *allowedPropertyNames = [aClass totalAllowedPropertyNames]; 302 | NSArray *ignoredPropertyNames = [aClass totalIgnoredPropertyNames]; 303 | 304 | [aClass enumerateProperties:^(MJProperty *property, BOOL *stop) { 305 | // 0.检测是否被忽略 306 | if (allowedPropertyNames.count && ![allowedPropertyNames containsObject:property.name]) return; 307 | if ([ignoredPropertyNames containsObject:property.name]) return; 308 | if (keys.count && ![keys containsObject:property.name]) return; 309 | if ([ignoredKeys containsObject:property.name]) return; 310 | 311 | // 1.取出属性值 312 | id value = [property valueFromObject:self]; 313 | if (!value) return; 314 | 315 | // 2.如果是模型属性 316 | MJType *type = property.type; 317 | Class typeClass = type.typeClass; 318 | Class objectClass = [property objectClassInArrayFromClass:[self class]]; 319 | if (!type.isFromFoundation && typeClass) { 320 | value = [value keyValues]; 321 | } else if (objectClass) { 322 | // 3.处理数组里面有模型的情况 323 | value = [objectClass keyValuesArrayWithObjectArray:value]; 324 | } else if (typeClass == [NSURL class]) { 325 | value = [value absoluteString]; 326 | } 327 | 328 | // 4.赋值 329 | NSArray *keys = [property keysFromClass:[self class]]; 330 | NSUInteger keyCount = keys.count; 331 | // 创建字典 332 | __block NSMutableDictionary *innerDict = keyValues; 333 | [keys enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop) { 334 | if (idx == keyCount - 1) { // 最后一个属性 335 | innerDict[key] = value; 336 | } else { // 字典 337 | NSMutableDictionary *tempDict = innerDict[key]; 338 | if (tempDict == nil) { 339 | tempDict = [NSMutableDictionary dictionary]; 340 | innerDict[key] = tempDict; 341 | } 342 | innerDict = tempDict; 343 | } 344 | }]; 345 | }]; 346 | 347 | // 去除系统自动增加的元素 348 | [keyValues removeObjectsForKeys:@[@"superclass", @"debugDescription", @"description", @"hash"]]; 349 | 350 | // 转换完毕 351 | if ([self respondsToSelector:@selector(objectDidFinishConvertingToKeyValues)]) { 352 | [self objectDidFinishConvertingToKeyValues]; 353 | } 354 | } @catch (NSException *exception) { 355 | MJBuildError(error, exception.reason); 356 | } 357 | 358 | return keyValues; 359 | } 360 | #pragma mark - 模型数组 -> 字典数组 361 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray 362 | { 363 | return [self keyValuesArrayWithObjectArray:objectArray error:nil]; 364 | } 365 | 366 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray error:(NSError *__autoreleasing *)error 367 | { 368 | return [self keyValuesArrayWithObjectArray:objectArray ignoredKeys:nil error:error]; 369 | } 370 | 371 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys 372 | { 373 | return [self keyValuesArrayWithObjectArray:objectArray keys:keys error:nil]; 374 | } 375 | 376 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys 377 | { 378 | return [self keyValuesArrayWithObjectArray:objectArray ignoredKeys:ignoredKeys error:nil]; 379 | } 380 | 381 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys error:(NSError *__autoreleasing *)error 382 | { 383 | return [self keyValuesArrayWithObjectArray:objectArray keys:keys ignoredKeys:nil error:error]; 384 | } 385 | 386 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys error:(NSError *__autoreleasing *)error 387 | { 388 | return [self keyValuesArrayWithObjectArray:objectArray keys:nil ignoredKeys:ignoredKeys error:error]; 389 | } 390 | 391 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys ignoredKeys:(NSArray *)ignoredKeys error:(NSError *__autoreleasing *)error 392 | { 393 | // 0.判断真实性 394 | MJAssertError([objectArray isKindOfClass:[NSArray class]], nil, error, @"objectArray参数不是一个数组"); 395 | 396 | // 1.创建数组 397 | NSMutableArray *keyValuesArray = [NSMutableArray array]; 398 | for (id object in objectArray) { 399 | if (keys) { 400 | [keyValuesArray addObject:[object keyValuesWithKeys:keys error:error]]; 401 | } else { 402 | [keyValuesArray addObject:[object keyValuesWithIgnoredKeys:ignoredKeys error:error]]; 403 | } 404 | } 405 | return keyValuesArray; 406 | } 407 | 408 | #pragma mark - 转换为JSON 409 | - (NSData *)JSONData 410 | { 411 | if ([self isKindOfClass:[NSString class]]) { 412 | return [((NSString *)self) dataUsingEncoding:NSUTF8StringEncoding]; 413 | } 414 | 415 | return [NSJSONSerialization dataWithJSONObject:[self JSONObject] options:kNilOptions error:nil]; 416 | } 417 | 418 | - (id)JSONObject 419 | { 420 | if ([self isKindOfClass:[NSString class]]) { 421 | return [NSJSONSerialization JSONObjectWithData:[((NSString *)self) dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil]; 422 | } 423 | 424 | return self.keyValues; 425 | } 426 | 427 | - (NSString *)JSONString 428 | { 429 | if ([self isKindOfClass:[NSString class]]) { 430 | return (NSString *)self; 431 | } 432 | 433 | return [[NSString alloc] initWithData:[self JSONData] encoding:NSUTF8StringEncoding]; 434 | } 435 | @end 436 | -------------------------------------------------------------------------------- /Class/Logic/RMCalendarLogic.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMCalendarLogic.m 3 | // RMCalendar 4 | // 5 | // Created by 迟浩东 on 15/7/15. 6 | // Copyright © 2015年 迟浩东(http://www.ruanman.net). All rights reserved. 7 | // 8 | 9 | #import "RMCalendarLogic.h" 10 | #import "NSDate+RMCalendarLogic.h" 11 | #import "TicketModel.h" 12 | 13 | @interface RMCalendarLogic() 14 | 15 | /** 16 | * 今天的日期 17 | */ 18 | @property (nonatomic, strong) NSDate *today; 19 | /** 20 | * 之后的日期 21 | */ 22 | @property (nonatomic, strong) NSDate *before; 23 | /** 24 | * 选中的日期 25 | */ 26 | @property (nonatomic, strong) NSDate *select; 27 | /** 28 | * 日期模型 29 | */ 30 | @property (nonatomic, strong) RMCalendarModel *model; 31 | /** 32 | * 价格模型数组 33 | */ 34 | @property (nonatomic, strong) NSArray *priceModelArr; 35 | 36 | @property (nonatomic, assign) BOOL isEnable; 37 | 38 | @property (nonatomic, assign) BOOL isDisplayChineseCalender; 39 | 40 | @end 41 | 42 | @implementation RMCalendarLogic 43 | 44 | #warning 初始化 模型数组,可根据功能进行修改 45 | - (NSArray *)priceModelArr { 46 | if (!_priceModelArr) { 47 | _priceModelArr = [NSArray array]; 48 | } 49 | return _priceModelArr; 50 | } 51 | 52 | -(NSMutableArray *)reloadCalendarView:(NSDate *)date selectDate:(NSDate *)selectDate needDays:(int)days showType:(CalendarShowType)type isEnable:(BOOL)isEnable priceModelArr:(NSArray *)arr isChineseCalendar:(BOOL)isChineseCalendar { 53 | self.isDisplayChineseCalender = isChineseCalendar; 54 | return [self reloadCalendarView:date selectDate:selectDate needDays:days showType:type isEnable:isEnable priceModelArr:arr]; 55 | } 56 | 57 | -(NSMutableArray *)reloadCalendarView:(NSDate *)date selectDate:(NSDate *)selectDate needDays:(int)days showType:(CalendarShowType)type isEnable:(BOOL)isEnable priceModelArr:(NSArray *)arr { 58 | self.isEnable = isEnable; 59 | return [self reloadCalendarView:date selectDate:selectDate needDays:days showType:type priceModelArr:arr]; 60 | } 61 | 62 | -(NSMutableArray *)reloadCalendarView:(NSDate *)date selectDate:(NSDate *)selectDate needDays:(int)days showType:(CalendarShowType)type priceModelArr:(NSArray *)arr { 63 | #warning 此处根据自己需求可修改 64 | // 存放价格模型 65 | self.priceModelArr = arr; 66 | return [self reloadCalendarView:date selectDate:selectDate needDays:days showType:type]; 67 | } 68 | 69 | - (NSMutableArray *)reloadCalendarView:(NSDate *)date selectDate:(NSDate *)selectDate needDays:(int)days showType:(CalendarShowType)type { 70 | //如果为空就从当天的日期开始 71 | if(date == nil){ 72 | date = [NSDate date]; 73 | } 74 | 75 | //默认选择中的时间 76 | if (selectDate == nil) { 77 | selectDate = date; 78 | } 79 | 80 | self.today = date;//起始日期 81 | 82 | self.before = [date dayInTheFollowingDay:days];//计算它days天以后的时间 83 | 84 | self.select = selectDate;//选择的日期 85 | 86 | NSDateComponents *todayDC= [self.today YMDComponents]; 87 | 88 | NSDateComponents *beforeDC= [self.before YMDComponents]; 89 | 90 | NSInteger todayYear = todayDC.year; 91 | 92 | NSInteger todayMonth = todayDC.month; 93 | 94 | NSInteger beforeYear = beforeDC.year; 95 | 96 | NSInteger beforeMonth = beforeDC.month; 97 | 98 | NSInteger months = (beforeYear-todayYear) * 12 + (beforeMonth - todayMonth); 99 | 100 | NSMutableArray *calendarMonth = [[NSMutableArray alloc]init];//每个月的dayModel数组 101 | 102 | if (type == CalendarShowTypeSingle) { 103 | months = 0; 104 | } 105 | 106 | for (int i = 0; i <= months; i++) { 107 | 108 | NSDate *month = [self.today dayInTheFollowingMonth:i]; 109 | NSMutableArray *calendarDays = [[NSMutableArray alloc]init]; 110 | [self calculateDaysInPreviousMonthWithDate:month andArray:calendarDays]; 111 | [self calculateDaysInCurrentMonthWithDate:month andArray:calendarDays]; 112 | if (type == CalendarShowTypeMultiple) { 113 | [self calculateDaysInFollowingMonthWithDate:month andArray:calendarDays];//计算下月份的天数 114 | } 115 | 116 | // [self calculateDaysIsWeekendandArray:calendarDays]; 117 | 118 | [calendarMonth insertObject:calendarDays atIndex:i]; 119 | } 120 | 121 | return calendarMonth; 122 | } 123 | 124 | //计算上月份的天数 125 | 126 | - (NSMutableArray *)calculateDaysInPreviousMonthWithDate:(NSDate *)date andArray:(NSMutableArray *)array 127 | { 128 | NSUInteger weeklyOrdinality = [[date firstDayOfCurrentMonth] weeklyOrdinality];//计算这个的第一天是礼拜几,并转为int型 129 | NSDate *dayInThePreviousMonth = [date dayInThePreviousMonth];//上一个月的NSDate对象 130 | int daysCount = (int)[dayInThePreviousMonth numberOfDaysInCurrentMonth];//计算上个月有多少天 131 | int partialDaysCount = (int)weeklyOrdinality - 1;//获取上月在这个月的日历上显示的天数 132 | NSDateComponents *components = [dayInThePreviousMonth YMDComponents];//获取年月日对象 133 | 134 | for (int i = daysCount - partialDaysCount + 1; i < daysCount + 1; ++i) { 135 | 136 | RMCalendarModel *calendarDay = [RMCalendarModel calendarWithYear:components.year month:components.month day:i]; 137 | calendarDay.style = CellDayTypeEmpty;//不显示 138 | calendarDay.isChineseCalendar = self.isDisplayChineseCalender; //此处需要赋值 农历是否展现 否则点击时产生错位 139 | [array addObject:calendarDay]; 140 | } 141 | 142 | 143 | return NULL; 144 | } 145 | 146 | 147 | 148 | //计算下月份的天数 149 | 150 | - (void)calculateDaysInFollowingMonthWithDate:(NSDate *)date andArray:(NSMutableArray *)array 151 | { 152 | NSUInteger weeklyOrdinality = [[date lastDayOfCurrentMonth] weeklyOrdinality]; 153 | if (weeklyOrdinality == 7) return ; 154 | 155 | NSUInteger partialDaysCount = 7 - weeklyOrdinality; 156 | NSDateComponents *components = [[date dayInTheFollowingMonth] YMDComponents]; 157 | 158 | for (int i = 1; i < partialDaysCount + 1; ++i) { 159 | RMCalendarModel *calendarDay = [RMCalendarModel calendarWithYear:components.year month:components.month day:i]; 160 | calendarDay.style = CellDayTypeEmpty; 161 | calendarDay.isChineseCalendar = self.isDisplayChineseCalender; //此处需要赋值 农历是否展现 否则点击时产生错位 162 | [array addObject:calendarDay]; 163 | } 164 | } 165 | 166 | 167 | //计算当月的天数 168 | 169 | - (void)calculateDaysInCurrentMonthWithDate:(NSDate *)date andArray:(NSMutableArray *)array 170 | { 171 | 172 | NSUInteger daysCount = [date numberOfDaysInCurrentMonth];//计算这个月有多少天 173 | NSDateComponents *components = [date YMDComponents];//今天日期的年月日 174 | 175 | for (int i = 1; i < daysCount + 1; ++i) { 176 | RMCalendarModel *calendarDay = [RMCalendarModel calendarWithYear:components.year month:components.month day:i]; 177 | calendarDay.week = [[calendarDay date]getWeekIntValueWithDate]; 178 | calendarDay.isChineseCalendar = self.isDisplayChineseCalender; //此处需要赋值 农历是否展现 否则点击时产生错位 179 | if (self.isDisplayChineseCalender) { 180 | calendarDay.Chinese_calendar = [self LunarForSolarYear:components.year Month:components.month Day:i]; 181 | [self LunarForSolarYear:calendarDay]; 182 | } 183 | [self changStyle:calendarDay]; 184 | [array addObject:calendarDay]; 185 | } 186 | } 187 | 188 | 189 | 190 | 191 | - (void)changStyle:(RMCalendarModel *)model 192 | { 193 | 194 | NSDateComponents *calendarToDay = [self.today YMDComponents];//今天 195 | NSDateComponents *calendarbefore = [self.before YMDComponents];//最后一天 196 | NSDateComponents *calendarSelect = [self.select YMDComponents];//默认选择的那一天 197 | model.isEnable = self.isEnable; 198 | 199 | //被点击选中 200 | if(calendarSelect.year == model.year & 201 | calendarSelect.month == model.month & 202 | calendarSelect.day == model.day){ 203 | 204 | model.style = CellDayTypeClick; 205 | self.model = model; 206 | //没被点击选中 207 | }else{ 208 | 209 | //昨天乃至过去的时间设置一个灰度 210 | if (calendarToDay.year >= model.year & 211 | calendarToDay.month >= model.month & 212 | calendarToDay.day > model.day) { 213 | 214 | model.style = CellDayTypePast; 215 | 216 | //之后的时间时间段 217 | }else if (calendarbefore.year <= model.year & 218 | calendarbefore.month <= model.month & 219 | calendarbefore.day <= model.day) { 220 | 221 | model.style = CellDayTypePast; 222 | 223 | //需要正常显示的时间段 224 | }else{ 225 | 226 | //周末 227 | if (model.week == 1 || model.week == 7){ 228 | model.style = CellDayTypeWeek; 229 | 230 | //工作日 231 | }else{ 232 | model.style = CellDayTypeFutur; 233 | } 234 | } 235 | } 236 | #warning for进行模型日期匹配,将价格和日期关联,此处可根据项目需求进行修改 237 | for (int i = 0; i < self.priceModelArr.count; i++) { 238 | TicketModel *tModel = self.priceModelArr[i]; 239 | if (tModel.year == model.year & 240 | tModel.month == model.month & 241 | tModel.day == model.day) { 242 | model.ticketModel = tModel; 243 | } 244 | } 245 | 246 | 247 | //=================================== 248 | //这里来判断节日 249 | //今天 250 | if (calendarToDay.year == model.year && 251 | calendarToDay.month == model.month && 252 | calendarToDay.day == model.day) { 253 | model.holiday = @"今天"; 254 | //明天 255 | // }else if(calendarToDay.year == calendarDay.year && 256 | // calendarToDay.month == calendarDay.month && 257 | // calendarToDay.day - calendarDay.day == -1){ 258 | // calendarDay.holiday = @"明天"; 259 | // 260 | // //后天 261 | // }else if(calendarToDay.year == calendarDay.year && 262 | // calendarToDay.month == calendarDay.month && 263 | // calendarToDay.day - calendarDay.day == -2){ 264 | // calendarDay.holiday = @"后天"; 265 | //1.1元旦 266 | }else if (model.month == 1 && 267 | model.day == 1){ 268 | model.holiday = @"元旦"; 269 | 270 | //2.14情人节 271 | }else if (model.month == 2 && 272 | model.day == 14){ 273 | model.holiday = @"情人节"; 274 | 275 | //3.8妇女节 276 | }else if (model.month == 3 && 277 | model.day == 8){ 278 | model.holiday = @"妇女节"; 279 | 280 | //5.1劳动节 281 | }else if (model.month == 5 && 282 | model.day == 1){ 283 | model.holiday = @"劳动节"; 284 | 285 | //6.1儿童节 286 | }else if (model.month == 6 && 287 | model.day == 1){ 288 | model.holiday = @"儿童节"; 289 | 290 | //8.1建军节 291 | }else if (model.month == 8 && 292 | model.day == 1){ 293 | model.holiday = @"建军节"; 294 | 295 | //9.10教师节 296 | }else if (model.month == 9 && 297 | model.day == 10){ 298 | model.holiday = @"教师节"; 299 | 300 | //10.1国庆节 301 | }else if (model.month == 10 && 302 | model.day == 1){ 303 | model.holiday = @"国庆节"; 304 | 305 | //11.1植树节 306 | }else if (model.month == 11 && 307 | model.day == 1){ 308 | model.holiday = @"植树节"; 309 | 310 | //11.11光棍节 311 | }else if (model.month == 11 && 312 | model.day == 11){ 313 | model.holiday = @"光棍节"; 314 | 315 | }else{ 316 | 317 | // 这里写其它的节日 318 | 319 | } 320 | 321 | } 322 | 323 | #pragma mark - 农历转换函数 324 | 325 | -(void)LunarForSolarYear:(RMCalendarModel *)calendarDay{ 326 | 327 | NSString *solarYear = [self LunarForSolarYear:calendarDay.year Month:calendarDay.month Day:calendarDay.day]; 328 | 329 | NSArray *solarYear_arr= [solarYear componentsSeparatedByString:@"-"]; 330 | 331 | if([solarYear_arr[0]isEqualToString:@"正月"] && 332 | [solarYear_arr[1]isEqualToString:@"初一"]){ 333 | 334 | //正月初一:春节 335 | calendarDay.holiday = @"春节"; 336 | 337 | }else if([solarYear_arr[0]isEqualToString:@"正月"] && 338 | [solarYear_arr[1]isEqualToString:@"十五"]){ 339 | 340 | 341 | //正月十五:元宵节 342 | calendarDay.holiday = @"元宵节"; 343 | 344 | }else if([solarYear_arr[0]isEqualToString:@"二月"] && 345 | [solarYear_arr[1]isEqualToString:@"初二"]){ 346 | 347 | //二月初二:春龙节(龙抬头) 348 | calendarDay.holiday = @"龙抬头"; 349 | 350 | }else if([solarYear_arr[0]isEqualToString:@"五月"] && 351 | [solarYear_arr[1]isEqualToString:@"初五"]){ 352 | 353 | //五月初五:端午节 354 | calendarDay.holiday = @"端午节"; 355 | 356 | }else if([solarYear_arr[0]isEqualToString:@"七月"] && 357 | [solarYear_arr[1]isEqualToString:@"初七"]){ 358 | 359 | //七月初七:七夕情人节 360 | calendarDay.holiday = @"七夕节"; 361 | 362 | }else if([solarYear_arr[0]isEqualToString:@"八月"] && 363 | [solarYear_arr[1]isEqualToString:@"十五"]){ 364 | 365 | //八月十五:中秋节 366 | calendarDay.holiday = @"中秋节"; 367 | 368 | }else if([solarYear_arr[0]isEqualToString:@"九月"] && 369 | [solarYear_arr[1]isEqualToString:@"初九"]){ 370 | 371 | //九月初九:重阳节、中国老年节(义务助老活动日) 372 | calendarDay.holiday = @"重阳节"; 373 | 374 | }else if([solarYear_arr[0]isEqualToString:@"腊月"] && 375 | [solarYear_arr[1]isEqualToString:@"初八"]){ 376 | 377 | //腊月初八:腊八节 378 | calendarDay.holiday = @"腊八节"; 379 | 380 | }else if([solarYear_arr[0]isEqualToString:@"腊月"] && 381 | [solarYear_arr[1]isEqualToString:@"二十四"]){ 382 | 383 | 384 | //腊月二十四 小年 385 | calendarDay.holiday = @"小年"; 386 | 387 | }else if([solarYear_arr[0]isEqualToString:@"腊月"] && 388 | [solarYear_arr[1]isEqualToString:@"三十"]){ 389 | 390 | //腊月三十(小月二十九):除夕 391 | calendarDay.holiday = @"除夕"; 392 | 393 | } 394 | 395 | if ([solarYear_arr[1] isEqualToString:@"初一"]) 396 | { 397 | calendarDay.Chinese_calendar = solarYear_arr[0]; 398 | } else { 399 | calendarDay.Chinese_calendar = solarYear_arr[1]; 400 | } 401 | 402 | 403 | 404 | } 405 | 406 | -(NSString *)LunarForSolarYear:(NSUInteger)wCurYear Month:(NSInteger)wCurMonth Day:(NSUInteger)wCurDay{ 407 | 408 | 409 | 410 | //农历日期名 411 | NSArray *cDayName = [NSArray arrayWithObjects:@"*",@"初一",@"初二",@"初三",@"初四",@"初五",@"初六",@"初七",@"初八",@"初九",@"初十", 412 | @"十一",@"十二",@"十三",@"十四",@"十五",@"十六",@"十七",@"十八",@"十九",@"二十", 413 | @"廿一",@"廿二",@"廿三",@"廿四",@"廿五",@"廿六",@"廿七",@"廿八",@"廿九",@"三十",nil]; 414 | 415 | //农历月份名 416 | NSArray *cMonName = [NSArray arrayWithObjects:@"*",@"正月",@"二月",@"三月",@"四月",@"五月",@"六月",@"七月",@"八月",@"九月",@"十月",@"十一月",@"腊月",nil]; 417 | 418 | //公历每月前面的天数 419 | const int wMonthAdd[12] = {0,31,59,90,120,151,181,212,243,273,304,334}; 420 | 421 | //农历数据 422 | const int wNongliData[100] = {2635,333387,1701,1748,267701,694,2391,133423,1175,396438 423 | ,3402,3749,331177,1453,694,201326,2350,465197,3221,3402 424 | ,400202,2901,1386,267611,605,2349,137515,2709,464533,1738 425 | ,2901,330421,1242,2651,199255,1323,529706,3733,1706,398762 426 | ,2741,1206,267438,2647,1318,204070,3477,461653,1386,2413 427 | ,330077,1197,2637,268877,3365,531109,2900,2922,398042,2395 428 | ,1179,267415,2635,661067,1701,1748,398772,2742,2391,330031 429 | ,1175,1611,200010,3749,527717,1452,2742,332397,2350,3222 430 | ,268949,3402,3493,133973,1386,464219,605,2349,334123,2709 431 | ,2890,267946,2773,592565,1210,2651,395863,1323,2707,265877}; 432 | 433 | static int nTheDate,nIsEnd,m,k,n,i,nBit; 434 | 435 | 436 | //计算到初始时间1921年2月8日的天数:1921-2-8(正月初一) 437 | nTheDate = (int)((wCurYear - 1921) * 365 + (wCurYear - 1921) / 4 + wCurDay + wMonthAdd[wCurMonth - 1] - 38); 438 | 439 | if((!(wCurYear % 4)) && (wCurMonth > 2)) 440 | nTheDate = nTheDate + 1; 441 | 442 | //计算农历天干、地支、月、日 443 | nIsEnd = 0; 444 | m = 0; 445 | while(nIsEnd != 1) 446 | { 447 | if(wNongliData[m] < 4095) 448 | k = 11; 449 | else 450 | k = 12; 451 | n = k; 452 | while(n>=0) 453 | { 454 | //获取wNongliData(m)的第n个二进制位的值 455 | nBit = wNongliData[m]; 456 | for(i=1;i wNongliData[m] / 65536 + 1) 482 | wCurMonth = wCurMonth - 1; 483 | } 484 | 485 | 486 | //生成农历月 487 | NSString *szNongliMonth; 488 | if (wCurMonth < 1){ 489 | szNongliMonth = [NSString stringWithFormat:@"闰%@",(NSString *)[cMonName objectAtIndex:-1 * wCurMonth]]; 490 | }else{ 491 | szNongliMonth = (NSString *)[cMonName objectAtIndex:wCurMonth]; 492 | } 493 | 494 | //生成农历日 495 | NSString *szNongliDay = [cDayName objectAtIndex:wCurDay]; 496 | 497 | //合并 498 | NSString *lunarDate = [NSString stringWithFormat:@"%@-%@",szNongliMonth,szNongliDay]; 499 | 500 | return lunarDate; 501 | } 502 | 503 | 504 | 505 | 506 | - (void)selectLogic:(RMCalendarModel *)dayModel 507 | { 508 | 509 | if (dayModel.style == CellDayTypeClick) { 510 | return; 511 | } 512 | 513 | dayModel.style = CellDayTypeClick; 514 | //周末 515 | if (self.model.week == 1 || self.model.week == 7){ 516 | self.model.style = CellDayTypeWeek; 517 | 518 | //工作日 519 | }else{ 520 | self.model.style = CellDayTypeFutur; 521 | } 522 | self.model = dayModel; 523 | } 524 | 525 | 526 | @end 527 | -------------------------------------------------------------------------------- /RMCalendar.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | EE4A4FF51B43E881004B6590 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = EE4A4FF41B43E881004B6590 /* main.m */; }; 11 | EE4A4FF81B43E881004B6590 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = EE4A4FF71B43E881004B6590 /* AppDelegate.m */; }; 12 | EE4A4FFB1B43E881004B6590 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EE4A4FFA1B43E881004B6590 /* ViewController.m */; }; 13 | EE4A4FFE1B43E881004B6590 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EE4A4FFC1B43E881004B6590 /* Main.storyboard */; }; 14 | EE4A50001B43E881004B6590 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EE4A4FFF1B43E881004B6590 /* Images.xcassets */; }; 15 | EE4A50031B43E881004B6590 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = EE4A50011B43E881004B6590 /* LaunchScreen.xib */; }; 16 | EE4A500F1B43E881004B6590 /* RMCalendarTests.m in Sources */ = {isa = PBXBuildFile; fileRef = EE4A500E1B43E881004B6590 /* RMCalendarTests.m */; }; 17 | EE4A503B1B43E8EF004B6590 /* NSDate+RMCalendarLogic.m in Sources */ = {isa = PBXBuildFile; fileRef = EE4A501B1B43E8EF004B6590 /* NSDate+RMCalendarLogic.m */; }; 18 | EE4A503C1B43E8EF004B6590 /* UIView+CustomFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = EE4A501D1B43E8EF004B6590 /* UIView+CustomFrame.m */; }; 19 | EE4A503D1B43E8EF004B6590 /* RMCalendarController.m in Sources */ = {isa = PBXBuildFile; fileRef = EE4A50201B43E8EF004B6590 /* RMCalendarController.m */; }; 20 | EE4A503E1B43E8EF004B6590 /* RMCalendarLogic.m in Sources */ = {isa = PBXBuildFile; fileRef = EE4A50231B43E8EF004B6590 /* RMCalendarLogic.m */; }; 21 | EE4A503F1B43E8EF004B6590 /* RMCalendarModel.m in Sources */ = {isa = PBXBuildFile; fileRef = EE4A50261B43E8EF004B6590 /* RMCalendarModel.m */; }; 22 | EE4A50401B43E8EF004B6590 /* CalendarDisableDate.png in Resources */ = {isa = PBXBuildFile; fileRef = EE4A50281B43E8EF004B6590 /* CalendarDisableDate.png */; }; 23 | EE4A50411B43E8EF004B6590 /* CalendarNormalDate.png in Resources */ = {isa = PBXBuildFile; fileRef = EE4A50291B43E8EF004B6590 /* CalendarNormalDate.png */; }; 24 | EE4A50421B43E8EF004B6590 /* CalendarPreviousMonth.png in Resources */ = {isa = PBXBuildFile; fileRef = EE4A502A1B43E8EF004B6590 /* CalendarPreviousMonth.png */; }; 25 | EE4A50431B43E8EF004B6590 /* CalendarPreviousMonth@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = EE4A502B1B43E8EF004B6590 /* CalendarPreviousMonth@2x.png */; }; 26 | EE4A50441B43E8EF004B6590 /* CalendarRow.png in Resources */ = {isa = PBXBuildFile; fileRef = EE4A502C1B43E8EF004B6590 /* CalendarRow.png */; }; 27 | EE4A50451B43E8EF004B6590 /* CalendarRow@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = EE4A502D1B43E8EF004B6590 /* CalendarRow@2x.png */; }; 28 | EE4A50461B43E8EF004B6590 /* CalendarRowBottom.png in Resources */ = {isa = PBXBuildFile; fileRef = EE4A502E1B43E8EF004B6590 /* CalendarRowBottom.png */; }; 29 | EE4A50471B43E8EF004B6590 /* CalendarRowBottom@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = EE4A502F1B43E8EF004B6590 /* CalendarRowBottom@2x.png */; }; 30 | EE4A50481B43E8EF004B6590 /* CalendarSelectedDate.png in Resources */ = {isa = PBXBuildFile; fileRef = EE4A50301B43E8EF004B6590 /* CalendarSelectedDate.png */; }; 31 | EE4A50491B43E8EF004B6590 /* CalendarSelectedDate@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = EE4A50311B43E8EF004B6590 /* CalendarSelectedDate@2x.png */; }; 32 | EE4A504A1B43E8EF004B6590 /* CalendarTodaysDate.png in Resources */ = {isa = PBXBuildFile; fileRef = EE4A50321B43E8EF004B6590 /* CalendarTodaysDate.png */; }; 33 | EE4A504B1B43E8EF004B6590 /* CalendarTodaysDate@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = EE4A50331B43E8EF004B6590 /* CalendarTodaysDate@2x.png */; }; 34 | EE4A504C1B43E8EF004B6590 /* RMCalendarCollectionViewLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = EE4A50361B43E8EF004B6590 /* RMCalendarCollectionViewLayout.m */; }; 35 | EE4A504D1B43E8EF004B6590 /* RMCalendarMonthHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = EE4A50381B43E8EF004B6590 /* RMCalendarMonthHeaderView.m */; }; 36 | EE4A504E1B43E8EF004B6590 /* RMCollectionCell.m in Sources */ = {isa = PBXBuildFile; fileRef = EE4A503A1B43E8EF004B6590 /* RMCollectionCell.m */; }; 37 | EE4A50501B43E902004B6590 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = EE4A504F1B43E902004B6590 /* Default-568h@2x.png */; }; 38 | EEDB721D1B4A1EA3003F6AC6 /* TicketModel.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDB721C1B4A1EA3003F6AC6 /* TicketModel.m */; }; 39 | EEDB72301B4A4A0C003F6AC6 /* MJConst.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDB72201B4A4A0C003F6AC6 /* MJConst.m */; }; 40 | EEDB72311B4A4A0C003F6AC6 /* MJFoundation.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDB72231B4A4A0C003F6AC6 /* MJFoundation.m */; }; 41 | EEDB72321B4A4A0C003F6AC6 /* MJProperty.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDB72251B4A4A0C003F6AC6 /* MJProperty.m */; }; 42 | EEDB72331B4A4A0C003F6AC6 /* MJType.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDB72271B4A4A0C003F6AC6 /* MJType.m */; }; 43 | EEDB72341B4A4A0C003F6AC6 /* NSObject+MJCoding.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDB72291B4A4A0C003F6AC6 /* NSObject+MJCoding.m */; }; 44 | EEDB72351B4A4A0C003F6AC6 /* NSObject+MJKeyValue.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDB722B1B4A4A0C003F6AC6 /* NSObject+MJKeyValue.m */; }; 45 | EEDB72361B4A4A0C003F6AC6 /* NSObject+MJProperty.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDB722D1B4A4A0C003F6AC6 /* NSObject+MJProperty.m */; }; 46 | EEDB72371B4A4A0C003F6AC6 /* NSString+MJExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDB722F1B4A4A0C003F6AC6 /* NSString+MJExtension.m */; }; 47 | /* End PBXBuildFile section */ 48 | 49 | /* Begin PBXContainerItemProxy section */ 50 | EE4A50091B43E881004B6590 /* PBXContainerItemProxy */ = { 51 | isa = PBXContainerItemProxy; 52 | containerPortal = EE4A4FE71B43E881004B6590 /* Project object */; 53 | proxyType = 1; 54 | remoteGlobalIDString = EE4A4FEE1B43E881004B6590; 55 | remoteInfo = RMCalendar; 56 | }; 57 | /* End PBXContainerItemProxy section */ 58 | 59 | /* Begin PBXFileReference section */ 60 | EE4A4FEF1B43E881004B6590 /* RMCalendar.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RMCalendar.app; sourceTree = BUILT_PRODUCTS_DIR; }; 61 | EE4A4FF31B43E881004B6590 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 62 | EE4A4FF41B43E881004B6590 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 63 | EE4A4FF61B43E881004B6590 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 64 | EE4A4FF71B43E881004B6590 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 65 | EE4A4FF91B43E881004B6590 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 66 | EE4A4FFA1B43E881004B6590 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 67 | EE4A4FFD1B43E881004B6590 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 68 | EE4A4FFF1B43E881004B6590 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 69 | EE4A50021B43E881004B6590 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 70 | EE4A50081B43E881004B6590 /* RMCalendarTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RMCalendarTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 71 | EE4A500D1B43E881004B6590 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 72 | EE4A500E1B43E881004B6590 /* RMCalendarTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RMCalendarTests.m; sourceTree = ""; }; 73 | EE4A501A1B43E8EF004B6590 /* NSDate+RMCalendarLogic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDate+RMCalendarLogic.h"; sourceTree = ""; }; 74 | EE4A501B1B43E8EF004B6590 /* NSDate+RMCalendarLogic.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDate+RMCalendarLogic.m"; sourceTree = ""; }; 75 | EE4A501C1B43E8EF004B6590 /* UIView+CustomFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+CustomFrame.h"; sourceTree = ""; }; 76 | EE4A501D1B43E8EF004B6590 /* UIView+CustomFrame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+CustomFrame.m"; sourceTree = ""; }; 77 | EE4A501F1B43E8EF004B6590 /* RMCalendarController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMCalendarController.h; sourceTree = ""; }; 78 | EE4A50201B43E8EF004B6590 /* RMCalendarController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMCalendarController.m; sourceTree = ""; }; 79 | EE4A50221B43E8EF004B6590 /* RMCalendarLogic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMCalendarLogic.h; sourceTree = ""; }; 80 | EE4A50231B43E8EF004B6590 /* RMCalendarLogic.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMCalendarLogic.m; sourceTree = ""; }; 81 | EE4A50251B43E8EF004B6590 /* RMCalendarModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMCalendarModel.h; sourceTree = ""; }; 82 | EE4A50261B43E8EF004B6590 /* RMCalendarModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMCalendarModel.m; sourceTree = ""; }; 83 | EE4A50281B43E8EF004B6590 /* CalendarDisableDate.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = CalendarDisableDate.png; sourceTree = ""; }; 84 | EE4A50291B43E8EF004B6590 /* CalendarNormalDate.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = CalendarNormalDate.png; sourceTree = ""; }; 85 | EE4A502A1B43E8EF004B6590 /* CalendarPreviousMonth.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = CalendarPreviousMonth.png; sourceTree = ""; }; 86 | EE4A502B1B43E8EF004B6590 /* CalendarPreviousMonth@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "CalendarPreviousMonth@2x.png"; sourceTree = ""; }; 87 | EE4A502C1B43E8EF004B6590 /* CalendarRow.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = CalendarRow.png; sourceTree = ""; }; 88 | EE4A502D1B43E8EF004B6590 /* CalendarRow@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "CalendarRow@2x.png"; sourceTree = ""; }; 89 | EE4A502E1B43E8EF004B6590 /* CalendarRowBottom.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = CalendarRowBottom.png; sourceTree = ""; }; 90 | EE4A502F1B43E8EF004B6590 /* CalendarRowBottom@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "CalendarRowBottom@2x.png"; sourceTree = ""; }; 91 | EE4A50301B43E8EF004B6590 /* CalendarSelectedDate.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = CalendarSelectedDate.png; sourceTree = ""; }; 92 | EE4A50311B43E8EF004B6590 /* CalendarSelectedDate@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "CalendarSelectedDate@2x.png"; sourceTree = ""; }; 93 | EE4A50321B43E8EF004B6590 /* CalendarTodaysDate.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = CalendarTodaysDate.png; sourceTree = ""; }; 94 | EE4A50331B43E8EF004B6590 /* CalendarTodaysDate@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "CalendarTodaysDate@2x.png"; sourceTree = ""; }; 95 | EE4A50351B43E8EF004B6590 /* RMCalendarCollectionViewLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMCalendarCollectionViewLayout.h; sourceTree = ""; }; 96 | EE4A50361B43E8EF004B6590 /* RMCalendarCollectionViewLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMCalendarCollectionViewLayout.m; sourceTree = ""; }; 97 | EE4A50371B43E8EF004B6590 /* RMCalendarMonthHeaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMCalendarMonthHeaderView.h; sourceTree = ""; }; 98 | EE4A50381B43E8EF004B6590 /* RMCalendarMonthHeaderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMCalendarMonthHeaderView.m; sourceTree = ""; }; 99 | EE4A50391B43E8EF004B6590 /* RMCollectionCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMCollectionCell.h; sourceTree = ""; }; 100 | EE4A503A1B43E8EF004B6590 /* RMCollectionCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMCollectionCell.m; sourceTree = ""; }; 101 | EE4A504F1B43E902004B6590 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 102 | EEDB721B1B4A1EA3003F6AC6 /* TicketModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TicketModel.h; sourceTree = ""; }; 103 | EEDB721C1B4A1EA3003F6AC6 /* TicketModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TicketModel.m; sourceTree = ""; }; 104 | EEDB721F1B4A4A0C003F6AC6 /* MJConst.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MJConst.h; sourceTree = ""; }; 105 | EEDB72201B4A4A0C003F6AC6 /* MJConst.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MJConst.m; sourceTree = ""; }; 106 | EEDB72211B4A4A0C003F6AC6 /* MJExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MJExtension.h; sourceTree = ""; }; 107 | EEDB72221B4A4A0C003F6AC6 /* MJFoundation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MJFoundation.h; sourceTree = ""; }; 108 | EEDB72231B4A4A0C003F6AC6 /* MJFoundation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MJFoundation.m; sourceTree = ""; }; 109 | EEDB72241B4A4A0C003F6AC6 /* MJProperty.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MJProperty.h; sourceTree = ""; }; 110 | EEDB72251B4A4A0C003F6AC6 /* MJProperty.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MJProperty.m; sourceTree = ""; }; 111 | EEDB72261B4A4A0C003F6AC6 /* MJType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MJType.h; sourceTree = ""; }; 112 | EEDB72271B4A4A0C003F6AC6 /* MJType.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MJType.m; sourceTree = ""; }; 113 | EEDB72281B4A4A0C003F6AC6 /* NSObject+MJCoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+MJCoding.h"; sourceTree = ""; }; 114 | EEDB72291B4A4A0C003F6AC6 /* NSObject+MJCoding.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+MJCoding.m"; sourceTree = ""; }; 115 | EEDB722A1B4A4A0C003F6AC6 /* NSObject+MJKeyValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+MJKeyValue.h"; sourceTree = ""; }; 116 | EEDB722B1B4A4A0C003F6AC6 /* NSObject+MJKeyValue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+MJKeyValue.m"; sourceTree = ""; }; 117 | EEDB722C1B4A4A0C003F6AC6 /* NSObject+MJProperty.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+MJProperty.h"; sourceTree = ""; }; 118 | EEDB722D1B4A4A0C003F6AC6 /* NSObject+MJProperty.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+MJProperty.m"; sourceTree = ""; }; 119 | EEDB722E1B4A4A0C003F6AC6 /* NSString+MJExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+MJExtension.h"; sourceTree = ""; }; 120 | EEDB722F1B4A4A0C003F6AC6 /* NSString+MJExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+MJExtension.m"; sourceTree = ""; }; 121 | /* End PBXFileReference section */ 122 | 123 | /* Begin PBXFrameworksBuildPhase section */ 124 | EE4A4FEC1B43E881004B6590 /* Frameworks */ = { 125 | isa = PBXFrameworksBuildPhase; 126 | buildActionMask = 2147483647; 127 | files = ( 128 | ); 129 | runOnlyForDeploymentPostprocessing = 0; 130 | }; 131 | EE4A50051B43E881004B6590 /* Frameworks */ = { 132 | isa = PBXFrameworksBuildPhase; 133 | buildActionMask = 2147483647; 134 | files = ( 135 | ); 136 | runOnlyForDeploymentPostprocessing = 0; 137 | }; 138 | /* End PBXFrameworksBuildPhase section */ 139 | 140 | /* Begin PBXGroup section */ 141 | EE4A4FE61B43E881004B6590 = { 142 | isa = PBXGroup; 143 | children = ( 144 | EE4A4FF11B43E881004B6590 /* RMCalendar */, 145 | EE4A500B1B43E881004B6590 /* RMCalendarTests */, 146 | EE4A4FF01B43E881004B6590 /* Products */, 147 | ); 148 | sourceTree = ""; 149 | }; 150 | EE4A4FF01B43E881004B6590 /* Products */ = { 151 | isa = PBXGroup; 152 | children = ( 153 | EE4A4FEF1B43E881004B6590 /* RMCalendar.app */, 154 | EE4A50081B43E881004B6590 /* RMCalendarTests.xctest */, 155 | ); 156 | name = Products; 157 | sourceTree = ""; 158 | }; 159 | EE4A4FF11B43E881004B6590 /* RMCalendar */ = { 160 | isa = PBXGroup; 161 | children = ( 162 | EEDB721E1B4A4A0C003F6AC6 /* MJExtension */, 163 | EE4A50181B43E8EF004B6590 /* Class */, 164 | EE4A4FF61B43E881004B6590 /* AppDelegate.h */, 165 | EE4A4FF71B43E881004B6590 /* AppDelegate.m */, 166 | EE4A4FF91B43E881004B6590 /* ViewController.h */, 167 | EE4A4FFA1B43E881004B6590 /* ViewController.m */, 168 | EE4A4FFC1B43E881004B6590 /* Main.storyboard */, 169 | EE4A4FFF1B43E881004B6590 /* Images.xcassets */, 170 | EE4A50011B43E881004B6590 /* LaunchScreen.xib */, 171 | EE4A4FF21B43E881004B6590 /* Supporting Files */, 172 | ); 173 | path = RMCalendar; 174 | sourceTree = ""; 175 | }; 176 | EE4A4FF21B43E881004B6590 /* Supporting Files */ = { 177 | isa = PBXGroup; 178 | children = ( 179 | EE4A504F1B43E902004B6590 /* Default-568h@2x.png */, 180 | EE4A4FF31B43E881004B6590 /* Info.plist */, 181 | EE4A4FF41B43E881004B6590 /* main.m */, 182 | ); 183 | name = "Supporting Files"; 184 | sourceTree = ""; 185 | }; 186 | EE4A500B1B43E881004B6590 /* RMCalendarTests */ = { 187 | isa = PBXGroup; 188 | children = ( 189 | EE4A500E1B43E881004B6590 /* RMCalendarTests.m */, 190 | EE4A500C1B43E881004B6590 /* Supporting Files */, 191 | ); 192 | path = RMCalendarTests; 193 | sourceTree = ""; 194 | }; 195 | EE4A500C1B43E881004B6590 /* Supporting Files */ = { 196 | isa = PBXGroup; 197 | children = ( 198 | EE4A500D1B43E881004B6590 /* Info.plist */, 199 | ); 200 | name = "Supporting Files"; 201 | sourceTree = ""; 202 | }; 203 | EE4A50181B43E8EF004B6590 /* Class */ = { 204 | isa = PBXGroup; 205 | children = ( 206 | EE4A50191B43E8EF004B6590 /* Category */, 207 | EE4A501E1B43E8EF004B6590 /* Controller */, 208 | EE4A50211B43E8EF004B6590 /* Logic */, 209 | EE4A50241B43E8EF004B6590 /* Model */, 210 | EE4A50271B43E8EF004B6590 /* Other */, 211 | EE4A50341B43E8EF004B6590 /* View */, 212 | ); 213 | path = Class; 214 | sourceTree = SOURCE_ROOT; 215 | }; 216 | EE4A50191B43E8EF004B6590 /* Category */ = { 217 | isa = PBXGroup; 218 | children = ( 219 | EE4A501A1B43E8EF004B6590 /* NSDate+RMCalendarLogic.h */, 220 | EE4A501B1B43E8EF004B6590 /* NSDate+RMCalendarLogic.m */, 221 | EE4A501C1B43E8EF004B6590 /* UIView+CustomFrame.h */, 222 | EE4A501D1B43E8EF004B6590 /* UIView+CustomFrame.m */, 223 | ); 224 | path = Category; 225 | sourceTree = ""; 226 | }; 227 | EE4A501E1B43E8EF004B6590 /* Controller */ = { 228 | isa = PBXGroup; 229 | children = ( 230 | EE4A501F1B43E8EF004B6590 /* RMCalendarController.h */, 231 | EE4A50201B43E8EF004B6590 /* RMCalendarController.m */, 232 | ); 233 | path = Controller; 234 | sourceTree = ""; 235 | }; 236 | EE4A50211B43E8EF004B6590 /* Logic */ = { 237 | isa = PBXGroup; 238 | children = ( 239 | EE4A50221B43E8EF004B6590 /* RMCalendarLogic.h */, 240 | EE4A50231B43E8EF004B6590 /* RMCalendarLogic.m */, 241 | ); 242 | path = Logic; 243 | sourceTree = ""; 244 | }; 245 | EE4A50241B43E8EF004B6590 /* Model */ = { 246 | isa = PBXGroup; 247 | children = ( 248 | EE4A50251B43E8EF004B6590 /* RMCalendarModel.h */, 249 | EE4A50261B43E8EF004B6590 /* RMCalendarModel.m */, 250 | EEDB721B1B4A1EA3003F6AC6 /* TicketModel.h */, 251 | EEDB721C1B4A1EA3003F6AC6 /* TicketModel.m */, 252 | ); 253 | path = Model; 254 | sourceTree = ""; 255 | }; 256 | EE4A50271B43E8EF004B6590 /* Other */ = { 257 | isa = PBXGroup; 258 | children = ( 259 | EE4A50281B43E8EF004B6590 /* CalendarDisableDate.png */, 260 | EE4A50291B43E8EF004B6590 /* CalendarNormalDate.png */, 261 | EE4A502A1B43E8EF004B6590 /* CalendarPreviousMonth.png */, 262 | EE4A502B1B43E8EF004B6590 /* CalendarPreviousMonth@2x.png */, 263 | EE4A502C1B43E8EF004B6590 /* CalendarRow.png */, 264 | EE4A502D1B43E8EF004B6590 /* CalendarRow@2x.png */, 265 | EE4A502E1B43E8EF004B6590 /* CalendarRowBottom.png */, 266 | EE4A502F1B43E8EF004B6590 /* CalendarRowBottom@2x.png */, 267 | EE4A50301B43E8EF004B6590 /* CalendarSelectedDate.png */, 268 | EE4A50311B43E8EF004B6590 /* CalendarSelectedDate@2x.png */, 269 | EE4A50321B43E8EF004B6590 /* CalendarTodaysDate.png */, 270 | EE4A50331B43E8EF004B6590 /* CalendarTodaysDate@2x.png */, 271 | ); 272 | path = Other; 273 | sourceTree = ""; 274 | }; 275 | EE4A50341B43E8EF004B6590 /* View */ = { 276 | isa = PBXGroup; 277 | children = ( 278 | EE4A50351B43E8EF004B6590 /* RMCalendarCollectionViewLayout.h */, 279 | EE4A50361B43E8EF004B6590 /* RMCalendarCollectionViewLayout.m */, 280 | EE4A50371B43E8EF004B6590 /* RMCalendarMonthHeaderView.h */, 281 | EE4A50381B43E8EF004B6590 /* RMCalendarMonthHeaderView.m */, 282 | EE4A50391B43E8EF004B6590 /* RMCollectionCell.h */, 283 | EE4A503A1B43E8EF004B6590 /* RMCollectionCell.m */, 284 | ); 285 | path = View; 286 | sourceTree = ""; 287 | }; 288 | EEDB721E1B4A4A0C003F6AC6 /* MJExtension */ = { 289 | isa = PBXGroup; 290 | children = ( 291 | EEDB721F1B4A4A0C003F6AC6 /* MJConst.h */, 292 | EEDB72201B4A4A0C003F6AC6 /* MJConst.m */, 293 | EEDB72211B4A4A0C003F6AC6 /* MJExtension.h */, 294 | EEDB72221B4A4A0C003F6AC6 /* MJFoundation.h */, 295 | EEDB72231B4A4A0C003F6AC6 /* MJFoundation.m */, 296 | EEDB72241B4A4A0C003F6AC6 /* MJProperty.h */, 297 | EEDB72251B4A4A0C003F6AC6 /* MJProperty.m */, 298 | EEDB72261B4A4A0C003F6AC6 /* MJType.h */, 299 | EEDB72271B4A4A0C003F6AC6 /* MJType.m */, 300 | EEDB72281B4A4A0C003F6AC6 /* NSObject+MJCoding.h */, 301 | EEDB72291B4A4A0C003F6AC6 /* NSObject+MJCoding.m */, 302 | EEDB722A1B4A4A0C003F6AC6 /* NSObject+MJKeyValue.h */, 303 | EEDB722B1B4A4A0C003F6AC6 /* NSObject+MJKeyValue.m */, 304 | EEDB722C1B4A4A0C003F6AC6 /* NSObject+MJProperty.h */, 305 | EEDB722D1B4A4A0C003F6AC6 /* NSObject+MJProperty.m */, 306 | EEDB722E1B4A4A0C003F6AC6 /* NSString+MJExtension.h */, 307 | EEDB722F1B4A4A0C003F6AC6 /* NSString+MJExtension.m */, 308 | ); 309 | path = MJExtension; 310 | sourceTree = ""; 311 | }; 312 | /* End PBXGroup section */ 313 | 314 | /* Begin PBXNativeTarget section */ 315 | EE4A4FEE1B43E881004B6590 /* RMCalendar */ = { 316 | isa = PBXNativeTarget; 317 | buildConfigurationList = EE4A50121B43E881004B6590 /* Build configuration list for PBXNativeTarget "RMCalendar" */; 318 | buildPhases = ( 319 | EE4A4FEB1B43E881004B6590 /* Sources */, 320 | EE4A4FEC1B43E881004B6590 /* Frameworks */, 321 | EE4A4FED1B43E881004B6590 /* Resources */, 322 | ); 323 | buildRules = ( 324 | ); 325 | dependencies = ( 326 | ); 327 | name = RMCalendar; 328 | productName = RMCalendar; 329 | productReference = EE4A4FEF1B43E881004B6590 /* RMCalendar.app */; 330 | productType = "com.apple.product-type.application"; 331 | }; 332 | EE4A50071B43E881004B6590 /* RMCalendarTests */ = { 333 | isa = PBXNativeTarget; 334 | buildConfigurationList = EE4A50151B43E881004B6590 /* Build configuration list for PBXNativeTarget "RMCalendarTests" */; 335 | buildPhases = ( 336 | EE4A50041B43E881004B6590 /* Sources */, 337 | EE4A50051B43E881004B6590 /* Frameworks */, 338 | EE4A50061B43E881004B6590 /* Resources */, 339 | ); 340 | buildRules = ( 341 | ); 342 | dependencies = ( 343 | EE4A500A1B43E881004B6590 /* PBXTargetDependency */, 344 | ); 345 | name = RMCalendarTests; 346 | productName = RMCalendarTests; 347 | productReference = EE4A50081B43E881004B6590 /* RMCalendarTests.xctest */; 348 | productType = "com.apple.product-type.bundle.unit-test"; 349 | }; 350 | /* End PBXNativeTarget section */ 351 | 352 | /* Begin PBXProject section */ 353 | EE4A4FE71B43E881004B6590 /* Project object */ = { 354 | isa = PBXProject; 355 | attributes = { 356 | LastUpgradeCheck = 0640; 357 | ORGANIZATIONNAME = "迟浩东"; 358 | TargetAttributes = { 359 | EE4A4FEE1B43E881004B6590 = { 360 | CreatedOnToolsVersion = 6.4; 361 | }; 362 | EE4A50071B43E881004B6590 = { 363 | CreatedOnToolsVersion = 6.4; 364 | TestTargetID = EE4A4FEE1B43E881004B6590; 365 | }; 366 | }; 367 | }; 368 | buildConfigurationList = EE4A4FEA1B43E881004B6590 /* Build configuration list for PBXProject "RMCalendar" */; 369 | compatibilityVersion = "Xcode 3.2"; 370 | developmentRegion = English; 371 | hasScannedForEncodings = 0; 372 | knownRegions = ( 373 | en, 374 | Base, 375 | ); 376 | mainGroup = EE4A4FE61B43E881004B6590; 377 | productRefGroup = EE4A4FF01B43E881004B6590 /* Products */; 378 | projectDirPath = ""; 379 | projectRoot = ""; 380 | targets = ( 381 | EE4A4FEE1B43E881004B6590 /* RMCalendar */, 382 | EE4A50071B43E881004B6590 /* RMCalendarTests */, 383 | ); 384 | }; 385 | /* End PBXProject section */ 386 | 387 | /* Begin PBXResourcesBuildPhase section */ 388 | EE4A4FED1B43E881004B6590 /* Resources */ = { 389 | isa = PBXResourcesBuildPhase; 390 | buildActionMask = 2147483647; 391 | files = ( 392 | EE4A50481B43E8EF004B6590 /* CalendarSelectedDate.png in Resources */, 393 | EE4A4FFE1B43E881004B6590 /* Main.storyboard in Resources */, 394 | EE4A504B1B43E8EF004B6590 /* CalendarTodaysDate@2x.png in Resources */, 395 | EE4A50451B43E8EF004B6590 /* CalendarRow@2x.png in Resources */, 396 | EE4A50031B43E881004B6590 /* LaunchScreen.xib in Resources */, 397 | EE4A50411B43E8EF004B6590 /* CalendarNormalDate.png in Resources */, 398 | EE4A50431B43E8EF004B6590 /* CalendarPreviousMonth@2x.png in Resources */, 399 | EE4A50441B43E8EF004B6590 /* CalendarRow.png in Resources */, 400 | EE4A50491B43E8EF004B6590 /* CalendarSelectedDate@2x.png in Resources */, 401 | EE4A50421B43E8EF004B6590 /* CalendarPreviousMonth.png in Resources */, 402 | EE4A504A1B43E8EF004B6590 /* CalendarTodaysDate.png in Resources */, 403 | EE4A50461B43E8EF004B6590 /* CalendarRowBottom.png in Resources */, 404 | EE4A50401B43E8EF004B6590 /* CalendarDisableDate.png in Resources */, 405 | EE4A50501B43E902004B6590 /* Default-568h@2x.png in Resources */, 406 | EE4A50471B43E8EF004B6590 /* CalendarRowBottom@2x.png in Resources */, 407 | EE4A50001B43E881004B6590 /* Images.xcassets in Resources */, 408 | ); 409 | runOnlyForDeploymentPostprocessing = 0; 410 | }; 411 | EE4A50061B43E881004B6590 /* Resources */ = { 412 | isa = PBXResourcesBuildPhase; 413 | buildActionMask = 2147483647; 414 | files = ( 415 | ); 416 | runOnlyForDeploymentPostprocessing = 0; 417 | }; 418 | /* End PBXResourcesBuildPhase section */ 419 | 420 | /* Begin PBXSourcesBuildPhase section */ 421 | EE4A4FEB1B43E881004B6590 /* Sources */ = { 422 | isa = PBXSourcesBuildPhase; 423 | buildActionMask = 2147483647; 424 | files = ( 425 | EEDB72341B4A4A0C003F6AC6 /* NSObject+MJCoding.m in Sources */, 426 | EE4A503E1B43E8EF004B6590 /* RMCalendarLogic.m in Sources */, 427 | EEDB72311B4A4A0C003F6AC6 /* MJFoundation.m in Sources */, 428 | EEDB721D1B4A1EA3003F6AC6 /* TicketModel.m in Sources */, 429 | EEDB72351B4A4A0C003F6AC6 /* NSObject+MJKeyValue.m in Sources */, 430 | EE4A503B1B43E8EF004B6590 /* NSDate+RMCalendarLogic.m in Sources */, 431 | EE4A504E1B43E8EF004B6590 /* RMCollectionCell.m in Sources */, 432 | EE4A4FFB1B43E881004B6590 /* ViewController.m in Sources */, 433 | EEDB72371B4A4A0C003F6AC6 /* NSString+MJExtension.m in Sources */, 434 | EE4A4FF81B43E881004B6590 /* AppDelegate.m in Sources */, 435 | EE4A4FF51B43E881004B6590 /* main.m in Sources */, 436 | EE4A503D1B43E8EF004B6590 /* RMCalendarController.m in Sources */, 437 | EE4A503F1B43E8EF004B6590 /* RMCalendarModel.m in Sources */, 438 | EE4A504C1B43E8EF004B6590 /* RMCalendarCollectionViewLayout.m in Sources */, 439 | EEDB72361B4A4A0C003F6AC6 /* NSObject+MJProperty.m in Sources */, 440 | EE4A503C1B43E8EF004B6590 /* UIView+CustomFrame.m in Sources */, 441 | EEDB72331B4A4A0C003F6AC6 /* MJType.m in Sources */, 442 | EE4A504D1B43E8EF004B6590 /* RMCalendarMonthHeaderView.m in Sources */, 443 | EEDB72321B4A4A0C003F6AC6 /* MJProperty.m in Sources */, 444 | EEDB72301B4A4A0C003F6AC6 /* MJConst.m in Sources */, 445 | ); 446 | runOnlyForDeploymentPostprocessing = 0; 447 | }; 448 | EE4A50041B43E881004B6590 /* Sources */ = { 449 | isa = PBXSourcesBuildPhase; 450 | buildActionMask = 2147483647; 451 | files = ( 452 | EE4A500F1B43E881004B6590 /* RMCalendarTests.m in Sources */, 453 | ); 454 | runOnlyForDeploymentPostprocessing = 0; 455 | }; 456 | /* End PBXSourcesBuildPhase section */ 457 | 458 | /* Begin PBXTargetDependency section */ 459 | EE4A500A1B43E881004B6590 /* PBXTargetDependency */ = { 460 | isa = PBXTargetDependency; 461 | target = EE4A4FEE1B43E881004B6590 /* RMCalendar */; 462 | targetProxy = EE4A50091B43E881004B6590 /* PBXContainerItemProxy */; 463 | }; 464 | /* End PBXTargetDependency section */ 465 | 466 | /* Begin PBXVariantGroup section */ 467 | EE4A4FFC1B43E881004B6590 /* Main.storyboard */ = { 468 | isa = PBXVariantGroup; 469 | children = ( 470 | EE4A4FFD1B43E881004B6590 /* Base */, 471 | ); 472 | name = Main.storyboard; 473 | sourceTree = ""; 474 | }; 475 | EE4A50011B43E881004B6590 /* LaunchScreen.xib */ = { 476 | isa = PBXVariantGroup; 477 | children = ( 478 | EE4A50021B43E881004B6590 /* Base */, 479 | ); 480 | name = LaunchScreen.xib; 481 | sourceTree = ""; 482 | }; 483 | /* End PBXVariantGroup section */ 484 | 485 | /* Begin XCBuildConfiguration section */ 486 | EE4A50101B43E881004B6590 /* Debug */ = { 487 | isa = XCBuildConfiguration; 488 | buildSettings = { 489 | ALWAYS_SEARCH_USER_PATHS = NO; 490 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 491 | CLANG_CXX_LIBRARY = "libc++"; 492 | CLANG_ENABLE_MODULES = YES; 493 | CLANG_ENABLE_OBJC_ARC = YES; 494 | CLANG_WARN_BOOL_CONVERSION = YES; 495 | CLANG_WARN_CONSTANT_CONVERSION = YES; 496 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 497 | CLANG_WARN_EMPTY_BODY = YES; 498 | CLANG_WARN_ENUM_CONVERSION = YES; 499 | CLANG_WARN_INT_CONVERSION = YES; 500 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 501 | CLANG_WARN_UNREACHABLE_CODE = YES; 502 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 503 | CODE_SIGN_IDENTITY = "iPhone Developer: Haodong Chi (J2Q67UL82P)"; 504 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Haodong Chi (J2Q67UL82P)"; 505 | COPY_PHASE_STRIP = NO; 506 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 507 | ENABLE_STRICT_OBJC_MSGSEND = YES; 508 | GCC_C_LANGUAGE_STANDARD = gnu99; 509 | GCC_DYNAMIC_NO_PIC = NO; 510 | GCC_NO_COMMON_BLOCKS = YES; 511 | GCC_OPTIMIZATION_LEVEL = 0; 512 | GCC_PREPROCESSOR_DEFINITIONS = ( 513 | "DEBUG=1", 514 | "$(inherited)", 515 | ); 516 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 517 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 518 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 519 | GCC_WARN_UNDECLARED_SELECTOR = YES; 520 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 521 | GCC_WARN_UNUSED_FUNCTION = YES; 522 | GCC_WARN_UNUSED_VARIABLE = YES; 523 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 524 | MTL_ENABLE_DEBUG_INFO = YES; 525 | ONLY_ACTIVE_ARCH = YES; 526 | SDKROOT = iphoneos; 527 | }; 528 | name = Debug; 529 | }; 530 | EE4A50111B43E881004B6590 /* Release */ = { 531 | isa = XCBuildConfiguration; 532 | buildSettings = { 533 | ALWAYS_SEARCH_USER_PATHS = NO; 534 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 535 | CLANG_CXX_LIBRARY = "libc++"; 536 | CLANG_ENABLE_MODULES = YES; 537 | CLANG_ENABLE_OBJC_ARC = YES; 538 | CLANG_WARN_BOOL_CONVERSION = YES; 539 | CLANG_WARN_CONSTANT_CONVERSION = YES; 540 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 541 | CLANG_WARN_EMPTY_BODY = YES; 542 | CLANG_WARN_ENUM_CONVERSION = YES; 543 | CLANG_WARN_INT_CONVERSION = YES; 544 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 545 | CLANG_WARN_UNREACHABLE_CODE = YES; 546 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 547 | CODE_SIGN_IDENTITY = "iPhone Developer: Haodong Chi (J2Q67UL82P)"; 548 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 549 | COPY_PHASE_STRIP = NO; 550 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 551 | ENABLE_NS_ASSERTIONS = NO; 552 | ENABLE_STRICT_OBJC_MSGSEND = YES; 553 | GCC_C_LANGUAGE_STANDARD = gnu99; 554 | GCC_NO_COMMON_BLOCKS = YES; 555 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 556 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 557 | GCC_WARN_UNDECLARED_SELECTOR = YES; 558 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 559 | GCC_WARN_UNUSED_FUNCTION = YES; 560 | GCC_WARN_UNUSED_VARIABLE = YES; 561 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 562 | MTL_ENABLE_DEBUG_INFO = NO; 563 | SDKROOT = iphoneos; 564 | VALIDATE_PRODUCT = YES; 565 | }; 566 | name = Release; 567 | }; 568 | EE4A50131B43E881004B6590 /* Debug */ = { 569 | isa = XCBuildConfiguration; 570 | buildSettings = { 571 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 572 | INFOPLIST_FILE = RMCalendar/Info.plist; 573 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 574 | PRODUCT_NAME = "$(TARGET_NAME)"; 575 | }; 576 | name = Debug; 577 | }; 578 | EE4A50141B43E881004B6590 /* Release */ = { 579 | isa = XCBuildConfiguration; 580 | buildSettings = { 581 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 582 | INFOPLIST_FILE = RMCalendar/Info.plist; 583 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 584 | PRODUCT_NAME = "$(TARGET_NAME)"; 585 | }; 586 | name = Release; 587 | }; 588 | EE4A50161B43E881004B6590 /* Debug */ = { 589 | isa = XCBuildConfiguration; 590 | buildSettings = { 591 | BUNDLE_LOADER = "$(TEST_HOST)"; 592 | FRAMEWORK_SEARCH_PATHS = ( 593 | "$(SDKROOT)/Developer/Library/Frameworks", 594 | "$(inherited)", 595 | ); 596 | GCC_PREPROCESSOR_DEFINITIONS = ( 597 | "DEBUG=1", 598 | "$(inherited)", 599 | ); 600 | INFOPLIST_FILE = RMCalendarTests/Info.plist; 601 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 602 | PRODUCT_NAME = "$(TARGET_NAME)"; 603 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RMCalendar.app/RMCalendar"; 604 | }; 605 | name = Debug; 606 | }; 607 | EE4A50171B43E881004B6590 /* Release */ = { 608 | isa = XCBuildConfiguration; 609 | buildSettings = { 610 | BUNDLE_LOADER = "$(TEST_HOST)"; 611 | FRAMEWORK_SEARCH_PATHS = ( 612 | "$(SDKROOT)/Developer/Library/Frameworks", 613 | "$(inherited)", 614 | ); 615 | INFOPLIST_FILE = RMCalendarTests/Info.plist; 616 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 617 | PRODUCT_NAME = "$(TARGET_NAME)"; 618 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RMCalendar.app/RMCalendar"; 619 | }; 620 | name = Release; 621 | }; 622 | /* End XCBuildConfiguration section */ 623 | 624 | /* Begin XCConfigurationList section */ 625 | EE4A4FEA1B43E881004B6590 /* Build configuration list for PBXProject "RMCalendar" */ = { 626 | isa = XCConfigurationList; 627 | buildConfigurations = ( 628 | EE4A50101B43E881004B6590 /* Debug */, 629 | EE4A50111B43E881004B6590 /* Release */, 630 | ); 631 | defaultConfigurationIsVisible = 0; 632 | defaultConfigurationName = Release; 633 | }; 634 | EE4A50121B43E881004B6590 /* Build configuration list for PBXNativeTarget "RMCalendar" */ = { 635 | isa = XCConfigurationList; 636 | buildConfigurations = ( 637 | EE4A50131B43E881004B6590 /* Debug */, 638 | EE4A50141B43E881004B6590 /* Release */, 639 | ); 640 | defaultConfigurationIsVisible = 0; 641 | defaultConfigurationName = Release; 642 | }; 643 | EE4A50151B43E881004B6590 /* Build configuration list for PBXNativeTarget "RMCalendarTests" */ = { 644 | isa = XCConfigurationList; 645 | buildConfigurations = ( 646 | EE4A50161B43E881004B6590 /* Debug */, 647 | EE4A50171B43E881004B6590 /* Release */, 648 | ); 649 | defaultConfigurationIsVisible = 0; 650 | defaultConfigurationName = Release; 651 | }; 652 | /* End XCConfigurationList section */ 653 | }; 654 | rootObject = EE4A4FE71B43E881004B6590 /* Project object */; 655 | } 656 | --------------------------------------------------------------------------------