├── Demo
├── .DS_Store
└── JWDatePickerView
│ ├── .DS_Store
│ ├── JWDatePickerView.xcodeproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcuserdata
│ │ │ └── zhujianwei.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ ├── xcuserdata
│ │ └── zhujianwei.xcuserdatad
│ │ │ ├── xcschemes
│ │ │ ├── xcschememanagement.plist
│ │ │ └── JWDatePickerView.xcscheme
│ │ │ └── xcdebugger
│ │ │ └── Breakpoints_v2.xcbkptlist
│ └── project.pbxproj
│ └── JWDatePickerView
│ ├── ViewController.h
│ ├── JWDatePickerView.xcdatamodeld
│ ├── .xccurrentversion
│ └── JWDatePickerView.xcdatamodel
│ │ └── contents
│ ├── main.m
│ ├── JWDatePickerView
│ ├── KBDatePickerViewkeyBoard.h
│ ├── JWDatePickerView.h
│ ├── KBDatePickerViewkeyBoard.m
│ └── JWDatePickerView.m
│ ├── AppDelegate.h
│ ├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
│ ├── Info.plist
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── ViewController.m
│ └── AppDelegate.m
├── Source
├── .DS_Store
└── PickerView.gif
├── JWDatePickerView
├── KBDatePickerViewkeyBoard.h
├── JWDatePickerView.h
├── KBDatePickerViewkeyBoard.m
└── JWDatePickerView.m
├── README.md
└── JWDatePickerView-Swift
├── JWDatePickerKeyBoardView.swift
├── JWPickerKeyBoardView.swift
└── JWDatePickerView.swift
/Demo/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GitHubOfJW/JWDatePickerView/HEAD/Demo/.DS_Store
--------------------------------------------------------------------------------
/Source/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GitHubOfJW/JWDatePickerView/HEAD/Source/.DS_Store
--------------------------------------------------------------------------------
/Source/PickerView.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GitHubOfJW/JWDatePickerView/HEAD/Source/PickerView.gif
--------------------------------------------------------------------------------
/Demo/JWDatePickerView/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GitHubOfJW/JWDatePickerView/HEAD/Demo/JWDatePickerView/.DS_Store
--------------------------------------------------------------------------------
/Demo/JWDatePickerView/JWDatePickerView.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Demo/JWDatePickerView/JWDatePickerView.xcodeproj/project.xcworkspace/xcuserdata/zhujianwei.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GitHubOfJW/JWDatePickerView/HEAD/Demo/JWDatePickerView/JWDatePickerView.xcodeproj/project.xcworkspace/xcuserdata/zhujianwei.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Demo/JWDatePickerView/JWDatePickerView/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // JWDatePickerView
4 | //
5 | // Created by 朱建伟 on 16/7/19.
6 | // Copyright © 2016年 zhujianwei. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ViewController : UIViewController
12 |
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/Demo/JWDatePickerView/JWDatePickerView/JWDatePickerView.xcdatamodeld/.xccurrentversion:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | _XCCurrentVersionName
6 | JWDatePickerView.xcdatamodel
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Demo/JWDatePickerView/JWDatePickerView/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // JWDatePickerView
4 | //
5 | // Created by 朱建伟 on 16/7/19.
6 | // Copyright © 2016年 zhujianwei. 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 |
--------------------------------------------------------------------------------
/Demo/JWDatePickerView/JWDatePickerView/JWDatePickerView.xcdatamodeld/JWDatePickerView.xcdatamodel/contents:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Demo/JWDatePickerView/JWDatePickerView.xcodeproj/xcuserdata/zhujianwei.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | JWDatePickerView.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 5BA28AD91D3DC2F300E4AFEA
16 |
17 | primary
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/JWDatePickerView/KBDatePickerViewkeyBoard.h:
--------------------------------------------------------------------------------
1 | //
2 | // KBSexkeyBoard.h
3 | // SunCarGuide
4 | //
5 | // Created by 朱建伟 on 15/12/17.
6 | // Copyright © 2015年 jryghq. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 |
12 | #import "JWDatePickerView.h"
13 |
14 | @interface KBDatePickerViewkeyBoard : UIView
15 |
16 | /**
17 | * 快捷初始化
18 | */
19 | -(instancetype)initWithFrame:(CGRect)frame title:(NSString*)title currentDayName:(NSString*)currentDayName;
20 |
21 |
22 | @property(nonatomic,strong,readonly)JWDatePickerView *pickerView;
23 |
24 |
25 | @property(nonatomic,copy)NSString *title;
26 |
27 |
28 | @property(nonatomic,copy)void(^didSelectedBlock)(NSDate *date,NSString* dateStr);
29 |
30 |
31 |
32 | @end
33 |
--------------------------------------------------------------------------------
/Demo/JWDatePickerView/JWDatePickerView/JWDatePickerView/KBDatePickerViewkeyBoard.h:
--------------------------------------------------------------------------------
1 | //
2 | // KBSexkeyBoard.h
3 | // SunCarGuide
4 | //
5 | // Created by 朱建伟 on 15/12/17.
6 | // Copyright © 2015年 jryghq. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 |
12 | #import "JWDatePickerView.h"
13 |
14 | @interface KBDatePickerViewkeyBoard : UIView
15 |
16 | /**
17 | * 快捷初始化
18 | */
19 | -(instancetype)initWithFrame:(CGRect)frame title:(NSString*)title currentDayName:(NSString*)currentDayName;
20 |
21 |
22 | @property(nonatomic,strong,readonly)JWDatePickerView *pickerView;
23 |
24 |
25 | @property(nonatomic,copy)NSString *title;
26 |
27 |
28 | @property(nonatomic,copy)void(^didSelectedBlock)(NSDate *date,NSString* dateStr);
29 |
30 |
31 |
32 | @end
33 |
--------------------------------------------------------------------------------
/Demo/JWDatePickerView/JWDatePickerView/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // JWDatePickerView
4 | //
5 | // Created by 朱建伟 on 16/7/19.
6 | // Copyright © 2016年 zhujianwei. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface AppDelegate : UIResponder
13 |
14 | @property (strong, nonatomic) UIWindow *window;
15 |
16 | @property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
17 | @property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
18 | @property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
19 |
20 | - (void)saveContext;
21 | - (NSURL *)applicationDocumentsDirectory;
22 |
23 |
24 | @end
25 |
26 |
--------------------------------------------------------------------------------
/Demo/JWDatePickerView/JWDatePickerView/Assets.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 | "idiom" : "ipad",
35 | "size" : "29x29",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "ipad",
40 | "size" : "29x29",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "40x40",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "40x40",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "76x76",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "76x76",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # JWDatePickerView
2 |
3 |
4 | ====介绍:本控件是为了扩展苹果的日历控件而编写,
5 |
6 | swift版本提供 10 个模式
7 | ```
8 | public enum JWDatePickerMode:Int{
9 |
10 | case dateAndTime// 年月日 时 分 秒
11 | case dateAndHour// 年月日 时
12 | case dateAndTimeRYear// 月日 时 分 秒
13 | case time// 时 分 秒
14 | case timeRSecond// 时 分
15 | case date// 年 月 日
16 | case dateAddHour// 年 月 日 时
17 | case dateAndTimeRSecond// 年月日 时 分
18 | case dateAndTimeRYearAndSecond// 月日 时 分 3
19 | case dateAndTimeForAllComponent// 年 月 日 时 分 秒
20 | }
21 | ```
22 |
23 | OC版本主要提供8 个模式
24 | ```
25 | JWDatePickerMode_DateAndTime,// 年月日 时 分 秒
26 | JWDatePickerMode_DateAndTimeRYear,// 月日 时 分 秒
27 | JWDatePickerMode_Time,// 时分秒
28 | JWDatePickerMode_TimeRSecond,//时分
29 | JWDatePickerMode_Date,// 年月日
30 | JWDatePickerMode_DateAddHour,// 年 月 日 时
31 | JWDatePickerMode_DateAndTimeRSecond,// 年月日 时 分
32 | JWDatePickerMode_DateAndTimeRYearAndSecond//月日 时 分
33 | ```
34 |
35 |
36 | ====介绍:通过代理指定单位
37 | ```
38 | -(NSString *)datePickerView:(JWDatePickerView *)datePickerView unitForCalendarUnit:(NSCalendarUnit)calendarUnit
39 | {
40 |
41 | switch (calendarUnit) {
42 | case NSCalendarUnitYear:
43 | return @"年";
44 | break;
45 | case NSCalendarUnitMonth:
46 | return @"月";
47 | break;
48 | case NSCalendarUnitDay:
49 | return @"日";
50 | break;
51 | case NSCalendarUnitHour:
52 | return @"时";
53 | break;
54 | case NSCalendarUnitMinute:
55 | return @"分";
56 | break;
57 | case NSCalendarUnitSecond:
58 | return @"秒";
59 | break;
60 | default:
61 | break;
62 | }
63 | return @" ";
64 | }
65 | ```
66 | ====演示
67 |
68 | 
69 |
--------------------------------------------------------------------------------
/Demo/JWDatePickerView/JWDatePickerView/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | 日历控件
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | LSRequiresIPhoneOS
26 |
27 | UILaunchStoryboardName
28 | LaunchScreen
29 | UIMainStoryboardFile
30 | Main
31 | UIRequiredDeviceCapabilities
32 |
33 | armv7
34 |
35 | UISupportedInterfaceOrientations
36 |
37 | UIInterfaceOrientationPortrait
38 |
39 | UISupportedInterfaceOrientations~ipad
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationPortraitUpsideDown
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/Demo/JWDatePickerView/JWDatePickerView/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/JWDatePickerView/JWDatePickerView.h:
--------------------------------------------------------------------------------
1 | //
2 | // JWDatePickerView.h
3 | // JWDatePickerView
4 | //
5 | // Created by 朱建伟 on 16/7/19.
6 | // Copyright © 2016年 zhujianwei. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 |
12 | typedef NS_ENUM(NSUInteger,JWDatePickerMode)
13 | {
14 | JWDatePickerMode_DateAndTime,// 年月日 时 分 秒 4
15 | JWDatePickerMode_DateAndTimeRYear,// 月日 时 分 秒 4
16 | JWDatePickerMode_Time,// 时分秒 3
17 | JWDatePickerMode_TimeRSecond,//时分 2
18 | JWDatePickerMode_Date,// 年月日 3
19 | JWDatePickerMode_DateAddHour,// 年 月 日 时 4
20 | JWDatePickerMode_DateAndTimeRSecond,// 年月日 时 分 3
21 | JWDatePickerMode_DateAndTimeRYearAndSecond//月日 时 分 3
22 | };
23 |
24 | @class JWDatePickerView;
25 | /**
26 | * 代理方法
27 | */
28 | @protocol JWDatePickerViewDelegate
29 |
30 | /**
31 | * 返回单位文字 比如说 参数NSCalendarUnitYear 返回 年 例如 2016年 没有则返回@""或者nil
32 | */
33 | -(NSString*)datePickerView:(JWDatePickerView*)datePickerView unitForCalendarUnit:(NSCalendarUnit)calendarUnit;
34 |
35 | @end
36 |
37 | @interface JWDatePickerView : UIView
38 |
39 | /**
40 | * delegate
41 | */
42 | @property(nonatomic,weak)id delegate;
43 |
44 | /**
45 | * 最小日期 如果是 不显示年的模式下 自动将最大日期设置在 一年内 只显示时分秒的同理
46 | */
47 | @property(nonatomic,strong)NSDate* minDate;
48 |
49 | /**
50 | * 当前日期 如果比最小日期小,设置最小日期为 date
51 | */
52 | @property(nonatomic,strong)NSDate* date;
53 |
54 | /**
55 | * 最大日起 如果是 不显示年的模式下 自动将最小日期设置在 一年内 只显示时分秒的同理
56 | */
57 | @property(nonatomic,strong)NSDate* maxDate;
58 |
59 | /**
60 | * pickerModel
61 | */
62 | @property(nonatomic,assign)JWDatePickerMode pickerMode;
63 |
64 |
65 | /**
66 | * font
67 | */
68 | @property(nonatomic,strong)UIFont* font;
69 |
70 |
71 |
72 | /**
73 | * minuteSpace 分钟间隔 条件 minuteSpace<30&&60%minuteSpace==0
74 | */
75 | @property(nonatomic,assign)NSUInteger minuteSpace;
76 |
77 | /**
78 | * secondSpace 秒间隔 条件 secondSpace<30&&60%secondSpace==0
79 | */
80 | @property(nonatomic,assign)NSUInteger secondSpace;
81 |
82 | /**
83 | * 刷新数据
84 | */
85 | -(void)reloadData;
86 |
87 |
88 | /**
89 | * 四舍五入 date 数据
90 | */
91 | -(NSDate*)getRoundDateWithDate:(NSDate*)date;
92 |
93 | /**
94 | * 获取一天中的 最小时间00:00:00 最大时间 23:59:59
95 | */
96 | -(NSDate*)getDayLastDateWithDate:(NSDate*)date max:(BOOL)isGetMax;
97 |
98 | /**
99 | * 获取日期字符串
100 | */
101 | -(NSString*)getDateStr;
102 | /**
103 | * 获取日期字符串
104 | */
105 | -(NSString*)getDateStrWithDateFormatterString:(NSString*)formatterStr;
106 | @end
107 |
--------------------------------------------------------------------------------
/Demo/JWDatePickerView/JWDatePickerView/JWDatePickerView/JWDatePickerView.h:
--------------------------------------------------------------------------------
1 | //
2 | // JWDatePickerView.h
3 | // JWDatePickerView
4 | //
5 | // Created by 朱建伟 on 16/7/19.
6 | // Copyright © 2016年 zhujianwei. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 |
12 | typedef NS_ENUM(NSUInteger,JWDatePickerMode)
13 | {
14 | JWDatePickerMode_DateAndTime,// 年月日 时 分 秒 4
15 | JWDatePickerMode_DateAndTimeRYear,// 月日 时 分 秒 4
16 | JWDatePickerMode_Time,// 时分秒 3
17 | JWDatePickerMode_TimeRSecond,//时分 2
18 | JWDatePickerMode_Date,// 年月日 3
19 | JWDatePickerMode_DateAddHour,// 年 月 日 时 4
20 | JWDatePickerMode_DateAndTimeRSecond,// 年月日 时 分 3
21 | JWDatePickerMode_DateAndTimeRYearAndSecond//月日 时 分 3
22 | };
23 |
24 | @class JWDatePickerView;
25 | /**
26 | * 代理方法
27 | */
28 | @protocol JWDatePickerViewDelegate
29 |
30 | /**
31 | * 返回单位文字 比如说 参数NSCalendarUnitYear 返回 年 例如 2016年 没有则返回@""或者nil
32 | */
33 | -(NSString*)datePickerView:(JWDatePickerView*)datePickerView unitForCalendarUnit:(NSCalendarUnit)calendarUnit;
34 |
35 | @end
36 |
37 | @interface JWDatePickerView : UIView
38 |
39 | /**
40 | * delegate
41 | */
42 | @property(nonatomic,weak)id delegate;
43 |
44 | /**
45 | * 最小日期 如果是 不显示年的模式下 自动将最大日期设置在 一年内 只显示时分秒的同理
46 | */
47 | @property(nonatomic,strong)NSDate* minDate;
48 |
49 | /**
50 | * 当前日期 如果比最小日期小,设置最小日期为 date
51 | */
52 | @property(nonatomic,strong)NSDate* date;
53 |
54 | /**
55 | * 最大日起 如果是 不显示年的模式下 自动将最小日期设置在 一年内 只显示时分秒的同理
56 | */
57 | @property(nonatomic,strong)NSDate* maxDate;
58 |
59 | /**
60 | * pickerModel
61 | */
62 | @property(nonatomic,assign)JWDatePickerMode pickerMode;
63 |
64 |
65 | /**
66 | * font
67 | */
68 | @property(nonatomic,strong)UIFont* font;
69 |
70 |
71 |
72 | /**
73 | * minuteSpace 分钟间隔 条件 minuteSpace<30&&60%minuteSpace==0
74 | */
75 | @property(nonatomic,assign)NSUInteger minuteSpace;
76 |
77 | /**
78 | * secondSpace 秒间隔 条件 secondSpace<30&&60%secondSpace==0
79 | */
80 | @property(nonatomic,assign)NSUInteger secondSpace;
81 |
82 | /**
83 | * 刷新数据
84 | */
85 | -(void)reloadData;
86 |
87 |
88 | /**
89 | * 四舍五入 date 数据
90 | */
91 | -(NSDate*)getRoundDateWithDate:(NSDate*)date;
92 |
93 | /**
94 | * 获取一天中的 最小时间00:00:00 最大时间 23:59:59
95 | */
96 | -(NSDate*)getDayLastDateWithDate:(NSDate*)date max:(BOOL)isGetMax;
97 |
98 | /**
99 | * 获取日期字符串
100 | */
101 | -(NSString*)getDateStr;
102 | /**
103 | * 获取日期字符串
104 | */
105 | -(NSString*)getDateStrWithDateFormatterString:(NSString*)formatterStr;
106 | @end
107 |
--------------------------------------------------------------------------------
/Demo/JWDatePickerView/JWDatePickerView/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/Demo/JWDatePickerView/JWDatePickerView.xcodeproj/xcuserdata/zhujianwei.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
8 |
14 |
15 |
16 |
18 |
30 |
31 |
32 |
34 |
46 |
47 |
48 |
50 |
56 |
57 |
58 |
60 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/Demo/JWDatePickerView/JWDatePickerView.xcodeproj/xcuserdata/zhujianwei.xcuserdatad/xcschemes/JWDatePickerView.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/Demo/JWDatePickerView/JWDatePickerView/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // JWDatePickerView
4 | //
5 | // Created by 朱建伟 on 16/7/19.
6 | // Copyright © 2016年 zhujianwei. All rights reserved.
7 | //
8 | #import "KBDatePickerViewkeyBoard.h"
9 | #import "JWDatePickerView.h"
10 | #import "ViewController.h"
11 |
12 | @interface ViewController ()
13 | /**
14 | * pickerView
15 | */
16 | @property(nonatomic,strong)JWDatePickerView* pickerView;
17 |
18 | /**
19 | * textField
20 | */
21 | @property(nonatomic,strong)UITextField* txtField;
22 |
23 | /**
24 | * kb
25 | */
26 | @property(nonatomic,strong)KBDatePickerViewkeyBoard* keyboard;
27 | @end
28 |
29 | @implementation ViewController
30 |
31 | - (void)viewDidLoad {
32 | [super viewDidLoad];
33 |
34 | self.navigationItem.title = @"日期键盘";
35 |
36 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"切换模式" style:(UIBarButtonItemStyleDone) target:self action:@selector(change)];
37 |
38 | [self.view addSubview:self.pickerView];
39 |
40 | [self.view addSubview:self.txtField];
41 | }
42 |
43 | -(void)change
44 | {
45 | if(self.pickerView.pickerMode ()
14 |
15 | var didConfirmDateClosure:ConfirmDateClosure?
16 |
17 |
18 | var isRemove:Bool = false
19 |
20 | var font:UIFont?{
21 | willSet{
22 | if let f = font {
23 | titleLabel?.font = f
24 | titleLabel?.text = "日期选择"
25 | cancelBtn?.titleLabel?.font = f
26 | confirmBtn?.titleLabel?.font = f
27 | }
28 | }
29 | }
30 |
31 |
32 | var title:String?{
33 | willSet{
34 | if let t = newValue{
35 | titleLabel?.text = t
36 | }
37 | }
38 | }
39 |
40 | //蒙版
41 | private var cover:UIControl = {
42 | let view:UIControl = UIControl(frame: ScreenBounds)
43 | view.backgroundColor = UIColor.black
44 | view.alpha = 0.4
45 |
46 | return view
47 | }()
48 |
49 | //取消按钮
50 | private var cancelBtn:UIButton?
51 |
52 | //确定按钮
53 | private var confirmBtn:UIButton?
54 |
55 | //头部标题
56 | private var titleLabel:UILabel?
57 |
58 | //头部View
59 | private var titleView:UIView?
60 |
61 | //pickerView
62 | let pickerView:JWDatePickerView = JWDatePickerView()
63 |
64 | override init(frame: CGRect) {
65 | super.init(frame: frame)
66 |
67 | backgroundColor = UIColor.white
68 |
69 | cover.addTarget(self, action: #selector(JWDatePickerKeyBoardView.exitKeyBoard), for: UIControlEvents.touchUpInside)
70 |
71 | // FontPrompt_120_218_317_416_515_614_712_810_908
72 | font = Font4
73 |
74 | //标题View
75 | titleView = UIView()
76 | titleView?.backgroundColor = UIColor.orange
77 | addSubview(titleView!)
78 |
79 | //取消按钮
80 | cancelBtn = UIButton()
81 | cancelBtn?.addTarget(self, action:#selector(JWDatePickerKeyBoardView.btnClick(btn:)), for: UIControlEvents.touchUpInside)
82 | cancelBtn?.titleLabel?.font = font
83 | cancelBtn?.setTitle("取消", for: UIControlState.normal)
84 | cancelBtn?.setTitle("取消", for: UIControlState.selected)
85 | cancelBtn?.setTitleColor(UIColor.white, for: UIControlState.normal)
86 | cancelBtn?.tag = 0
87 | titleView?.addSubview(cancelBtn!)
88 |
89 | //确定按钮
90 | confirmBtn = UIButton()
91 | confirmBtn?.addTarget(self, action:#selector(JWDatePickerKeyBoardView.btnClick(btn:)), for: UIControlEvents.touchUpInside)
92 | confirmBtn?.titleLabel?.font = font
93 | confirmBtn?.setTitle("确定", for: UIControlState.normal)
94 | confirmBtn?.setTitle("确定", for: UIControlState.selected)
95 | confirmBtn?.setTitleColor(UIColor.white, for: UIControlState.normal)
96 | confirmBtn?.tag = 1
97 | titleView?.addSubview(confirmBtn!)
98 |
99 | //标题
100 | titleLabel = UILabel()
101 | titleLabel?.textAlignment = NSTextAlignment.center
102 | titleLabel?.font = font
103 | titleLabel?.text = title
104 | titleLabel?.textColor = UIColor.white
105 | titleView?.addSubview(titleLabel!)
106 |
107 | //pickerView
108 | addSubview(pickerView)
109 | }
110 |
111 |
112 | internal func btnClick(btn:UIButton) {
113 | if btn.tag == 1 {
114 | if let closure = didConfirmDateClosure{
115 | if let date = pickerView.date{
116 | closure(date)
117 | }
118 | }
119 | }
120 |
121 | cover.alpha = 0.021;
122 | UIApplication.shared.keyWindow?.endEditing(true)
123 |
124 | }
125 |
126 | override func layoutSubviews() {
127 | super.layoutSubviews()
128 |
129 | //titleView
130 | setH(256)
131 |
132 | let titleViewX:CGFloat = 0
133 | let titleViewY:CGFloat = 0
134 | let titleViewW:CGFloat = bounds.width
135 | let titleViewH:CGFloat = 50
136 | titleView?.frame = CGRect(x: titleViewX, y: titleViewY, width: titleViewW, height: titleViewH)
137 |
138 | let cancelX:CGFloat = 0
139 | let cancelY:CGFloat = 0
140 | let cancelW:CGFloat = 80
141 | let cancelH:CGFloat = titleViewH
142 | cancelBtn?.frame = CGRect(x: cancelX, y: cancelY, width: cancelW, height: cancelH)
143 |
144 | let confirmW:CGFloat = cancelW
145 | let confirmH:CGFloat = titleViewH
146 | let confirmX:CGFloat = bounds.width - confirmW
147 | let confirmY:CGFloat = 0
148 | confirmBtn?.frame = CGRect(x: confirmX, y: confirmY, width: confirmW, height: confirmH)
149 |
150 | let titleW:CGFloat = bounds.width - cancelW*2
151 | let titleH:CGFloat = titleViewH
152 | let titleX:CGFloat = (cancelBtn?.frame.maxX)!
153 | let titleY:CGFloat = 0
154 | titleLabel?.frame = CGRect(x: titleX, y: titleY, width: titleW, height: titleH)
155 |
156 |
157 | let pickerX:CGFloat = 0
158 | let pickerY:CGFloat = titleViewH
159 | let pickerW:CGFloat = titleViewW
160 | let pickerH:CGFloat = bounds.size.height - titleViewH
161 | pickerView.frame = CGRect(x: pickerX, y: pickerY, width: pickerW, height: pickerH)
162 |
163 | }
164 |
165 | required init?(coder aDecoder: NSCoder) {
166 | fatalError("init(coder:) has not been implemented")
167 | }
168 |
169 |
170 | /**
171 | * 此方法当 自定键盘移动到窗口上调用
172 | */
173 | override func didMoveToWindow() {
174 | super.didMoveToWindow()
175 | if isRemove == false {
176 | let window:UIWindow = UIApplication.shared.keyWindow!
177 | cover.frame = ScreenBounds
178 | cover.alpha = 0.4
179 | window.addSubview(cover)
180 | }else
181 | {
182 | isRemove = false
183 | }
184 | }
185 |
186 |
187 | /**
188 | * 移除时 将蒙板一并移除
189 | */
190 | override func removeFromSuperview() {
191 | isRemove = true
192 | cover.removeFromSuperview()
193 |
194 | super.removeFromSuperview()
195 | }
196 |
197 |
198 | func exitKeyBoard() {
199 | cover.alpha = 0.021
200 | UIApplication.shared.keyWindow?.endEditing(true)
201 | }
202 |
203 | }
204 |
--------------------------------------------------------------------------------
/Demo/JWDatePickerView/JWDatePickerView/JWDatePickerView/KBDatePickerViewkeyBoard.m:
--------------------------------------------------------------------------------
1 | //
2 | // KBSexkeyBoard.m
3 | // SunCarGuide
4 | //
5 | // Created by 朱建伟 on 15/12/17.
6 | // Copyright © 2015年 jryghq. All rights reserved.
7 | //
8 | #import "KBDatePickerViewkeyBoard.h"
9 | @interface KBDatePickerViewkeyBoard()
10 | @property(nonatomic,strong)UIControl *cover;
11 |
12 | @property(nonatomic,strong)UIView *titleView;
13 | @property(nonatomic,strong)UILabel *titleLabel;
14 | @property(nonatomic,strong)UIButton *cancelBtn;
15 | @property(nonatomic,strong)UIButton *confirmBtn;
16 |
17 |
18 | @property(nonatomic,strong)NSString *currentTitle;
19 |
20 | @property(nonatomic,assign)BOOL isRemove;
21 |
22 | @property(nonatomic,assign)BOOL flag;
23 |
24 |
25 | @end
26 |
27 | @implementation KBDatePickerViewkeyBoard
28 |
29 | /**
30 | * 快捷初始化
31 | */
32 | -(instancetype)initWithFrame:(CGRect)frame title:(NSString *)title currentDayName:(NSString *)currentDayName
33 | {
34 | if (self = [self initWithFrame:frame]) {
35 | self.title =title;
36 | self.titleLabel.text = title;
37 | self.currentTitle = currentDayName;
38 | }
39 | return self;
40 | }
41 |
42 |
43 | /**
44 | * 初始化
45 | */
46 | -(instancetype)initWithFrame:(CGRect)frame
47 | {
48 | if(self = [super initWithFrame:frame])
49 | {
50 | self.flag = YES;
51 |
52 | [self setClipsToBounds:NO];
53 |
54 | _cover = [[UIControl alloc] init];
55 | _cover.backgroundColor = [UIColor blackColor];
56 | [_cover addTarget:self
57 | action:@selector(ExitKeyboard) forControlEvents:(UIControlEventTouchUpInside)];
58 | _cover.alpha = 0.4;
59 |
60 | //标题View
61 | _titleView = [[UIView alloc] init];
62 | [self addSubview:_titleView ];
63 |
64 | //标题
65 | _titleLabel =[[UILabel alloc] init];
66 | _titleLabel.text = @"请选择";
67 | // CGFloat titleValue = 160;
68 | _titleLabel.textColor = [UIColor orangeColor];//[UIColor colorWithRed:(titleValue/255.0) green:(titleValue/255.0) blue:(titleValue/255.0) alpha:1];
69 | _titleLabel.textAlignment = NSTextAlignmentCenter;
70 | _titleLabel.font = [UIFont systemFontOfSize:16];
71 | [_titleView addSubview:_titleLabel];
72 |
73 | //取消
74 | _cancelBtn = [[UIButton alloc] init];
75 | [_cancelBtn setTitleColor:[UIColor orangeColor]forState:(UIControlStateNormal)];
76 | [_cancelBtn setTitle:NSLocalizedString(@"取消",nil) forState:(UIControlStateNormal)];
77 | _cancelBtn.titleLabel.font =[UIFont systemFontOfSize:16];
78 | _cancelBtn.tag = 0;
79 | [_cancelBtn addTarget:self
80 | action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
81 | [_titleView addSubview:_cancelBtn];
82 |
83 | //确定
84 | _confirmBtn = [[UIButton alloc] init];
85 | [_confirmBtn setTitleColor:[UIColor orangeColor]forState:(UIControlStateNormal)];
86 | [_confirmBtn setTitle:NSLocalizedString(@"确定",nil) forState:(UIControlStateNormal)];
87 | _confirmBtn.titleLabel.font =[UIFont systemFontOfSize:16];
88 | _confirmBtn.tag = 1;
89 | [_confirmBtn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
90 | [_titleView addSubview:_confirmBtn];
91 |
92 |
93 | //pickerView
94 | _pickerView =[[JWDatePickerView alloc] init];
95 | _pickerView.backgroundColor = [UIColor whiteColor];
96 | [self addSubview:_pickerView];
97 |
98 | }
99 | return self;
100 | }
101 |
102 |
103 | -(void)layoutSubviews
104 | {
105 | [super layoutSubviews];
106 |
107 | CGFloat width = self.bounds.size.width;
108 | CGFloat height = 216;
109 | CGFloat margin = 10;
110 |
111 | CGFloat btnW = 80;
112 |
113 | CGFloat titleViewW = width;
114 | CGFloat titleViewH = 44;
115 | CGFloat titleViewX =0;
116 | CGFloat titleViewY =0;
117 | self.titleView.frame = CGRectMake(titleViewX, titleViewY, titleViewW, titleViewH);
118 |
119 | CGFloat cancelBtnW =btnW;
120 | CGFloat cancelBtnH = titleViewH;
121 | CGFloat cancelBtnX = margin;
122 | CGFloat cancelBtnY = 0;
123 | self.cancelBtn.frame =CGRectMake(cancelBtnX, cancelBtnY, cancelBtnW, cancelBtnH);
124 |
125 |
126 | CGFloat confirmBtnW = btnW;
127 | CGFloat confirmBtnH = titleViewH;
128 | CGFloat confirmBtnX = width - margin - confirmBtnW;
129 | CGFloat confirmBtnY = 0;
130 | self.confirmBtn.frame =CGRectMake(confirmBtnX, confirmBtnY, confirmBtnW, confirmBtnH);
131 |
132 |
133 | CGFloat titleLabelH = titleViewH;
134 | CGFloat titleLabelX = (cancelBtnX+cancelBtnW);
135 | CGFloat titleLabelW = confirmBtnX - titleLabelX;
136 | CGFloat titleLabelY = 0;
137 | self.titleLabel.frame = CGRectMake(titleLabelX, titleLabelY, titleLabelW, titleLabelH);
138 |
139 |
140 | CGFloat pickerViewX = 0;
141 | CGFloat pickerViewY = titleViewH;
142 | CGFloat pickerViewW = width;
143 | CGFloat pickerViewH = height - pickerViewY+margin;
144 | self.pickerView.frame = CGRectMake(pickerViewX, pickerViewY, pickerViewW, pickerViewH);
145 |
146 | }
147 |
148 |
149 | -(void)setTitle:(NSString *)title
150 | {
151 | _title = title;
152 |
153 | self.titleLabel.text = title;
154 |
155 | }
156 |
157 |
158 | /**
159 | * 此方法当 自定键盘移动到窗口上调用
160 | */
161 | -(void)didMoveToWindow
162 | {
163 | [super didMoveToWindow];
164 | if (!self.isRemove) {
165 | UIWindow *window = [UIApplication sharedApplication].keyWindow;
166 | self.cover.frame = CGRectMake(0,0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
167 | self.cover.alpha = 0.4;
168 | [window addSubview:self.cover];
169 | }else
170 | {
171 | self.isRemove = NO;
172 | }
173 | }
174 |
175 |
176 |
177 | /**
178 | * 移除时 将蒙板一并移除
179 | */
180 | -(void)removeFromSuperview
181 | {
182 | self.isRemove = YES;
183 | [self.cover removeFromSuperview];
184 | [super removeFromSuperview];
185 | }
186 |
187 |
188 | -(void)btnClick:(UIButton*)btn
189 | {
190 | if (btn.tag) {//确定
191 | if (self.didSelectedBlock&&self.pickerView.date) {
192 | self.didSelectedBlock(self.pickerView.date,[self.pickerView getDateStr]);
193 | }
194 | }
195 |
196 | self.cover.alpha = 0.021;
197 |
198 | [[UIApplication sharedApplication].keyWindow endEditing:YES];
199 | }
200 |
201 |
202 | -(void)ExitKeyboard{
203 | self.cover.alpha = 0.021;
204 | [[UIApplication sharedApplication].keyWindow endEditing:YES];
205 | }
206 |
207 | @end
208 |
--------------------------------------------------------------------------------
/JWDatePickerView-Swift/JWPickerKeyBoardView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // JWDatePickerKeyBoardView.swift
3 | // CarServer
4 | //
5 | // Created by 朱建伟 on 2016/10/17.
6 | // Copyright © 2016年 zhujianwei. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class JWPickerKeyBoardView: UIView ,UIPickerViewDelegate,UIPickerViewDataSource{
12 |
13 | typealias ConfirmDateClosure = (Int) -> ()
14 |
15 | var didConfirmClosure:ConfirmDateClosure?
16 |
17 | var numberClosure:(()->Int)?
18 |
19 | var titleClosure:((Int)->String)?
20 |
21 | var isRemove:Bool = false
22 |
23 | var font:UIFont?{
24 | willSet{
25 | if let f = font {
26 | titleLabel?.font = f
27 | titleLabel?.text = "日期选择"
28 | cancelBtn?.titleLabel?.font = f
29 | confirmBtn?.titleLabel?.font = f
30 | }
31 | }
32 | }
33 |
34 |
35 | var title:String?{
36 | willSet{
37 | if let t = newValue{
38 | titleLabel?.text = t
39 | }
40 | }
41 | }
42 |
43 | //蒙版
44 | private var cover:UIControl = {
45 | let view:UIControl = UIControl(frame: ScreenBounds)
46 | view.backgroundColor = UIColor.black
47 | view.alpha = 0.4
48 |
49 | return view
50 | }()
51 |
52 | //取消按钮
53 | private var cancelBtn:UIButton?
54 |
55 | //确定按钮
56 | private var confirmBtn:UIButton?
57 |
58 | //头部标题
59 | private var titleLabel:UILabel?
60 |
61 | //头部View
62 | private var titleView:UIView?
63 |
64 | //pickerView
65 | let pickerView:UIPickerView = UIPickerView()
66 |
67 | override init(frame: CGRect) {
68 | super.init(frame: frame)
69 |
70 | backgroundColor = UIColor.white
71 |
72 | pickerView.delegate = self
73 | pickerView.dataSource = self
74 |
75 | cover.addTarget(self, action: #selector(JWDatePickerKeyBoardView.exitKeyBoard), for: UIControlEvents.touchUpInside)
76 |
77 | // FontPrompt_120_218_317_416_515_614_712_810_908
78 | font = Font4
79 |
80 | //标题View
81 | titleView = UIView()
82 | let rgb:CGFloat = 220/255.0
83 | titleView?.backgroundColor = UIColor(red: rgb, green: rgb, blue: rgb, alpha: 1)
84 | addSubview(titleView!)
85 |
86 | //取消按钮
87 | cancelBtn = UIButton()
88 | cancelBtn?.addTarget(self, action:#selector(JWDatePickerKeyBoardView.btnClick(btn:)), for: UIControlEvents.touchUpInside)
89 | cancelBtn?.titleLabel?.font = font
90 | cancelBtn?.setTitle("取消", for: UIControlState.normal)
91 | cancelBtn?.setTitle("取消", for: UIControlState.selected)
92 | cancelBtn?.setTitleColor(UIColor.orange, for: UIControlState.normal)
93 | cancelBtn?.tag = 0
94 | titleView?.addSubview(cancelBtn!)
95 |
96 | //确定按钮
97 | confirmBtn = UIButton()
98 | confirmBtn?.addTarget(self, action:#selector(JWDatePickerKeyBoardView.btnClick(btn:)), for: UIControlEvents.touchUpInside)
99 | confirmBtn?.titleLabel?.font = font
100 | confirmBtn?.setTitle("确定", for: UIControlState.normal)
101 | confirmBtn?.setTitle("确定", for: UIControlState.selected)
102 | confirmBtn?.setTitleColor(UIColor.orange, for: UIControlState.normal)
103 | confirmBtn?.tag = 1
104 | titleView?.addSubview(confirmBtn!)
105 |
106 | //标题
107 | titleLabel = UILabel()
108 | titleLabel?.textAlignment = NSTextAlignment.center
109 | titleLabel?.font = font
110 | titleLabel?.text = title
111 | titleLabel?.textColor = FontGrayColor
112 | titleView?.addSubview(titleLabel!)
113 |
114 | //pickerView
115 | addSubview(pickerView)
116 | }
117 |
118 |
119 | func numberOfComponents(in pickerView: UIPickerView) -> Int {
120 | return 1
121 | }
122 |
123 |
124 |
125 | func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
126 | if let closure = self.numberClosure{
127 | if self.titleClosure != nil{
128 | return closure()
129 | }
130 | }
131 |
132 | return 0
133 |
134 | }
135 |
136 | //返回选项高度
137 | internal func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
138 | return pickerView.bounds.height/5
139 | }
140 |
141 |
142 | //返回label
143 | internal func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
144 |
145 | let title:String = titleClosure!(row)
146 |
147 | var label:UILabel? = nil
148 |
149 | if view != nil {
150 | label = view as! UILabel?
151 | }else{
152 | label = UILabel()
153 | label?.textAlignment = NSTextAlignment.center
154 | label?.textColor = FontGrayColor
155 | // Font_120_218_317_416_515_614_712_810_908
156 | label?.font = Font4
157 | label?.text = title
158 | }
159 | return label!
160 | }
161 |
162 | private var currentIndex:Int = 0
163 | func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
164 | currentIndex = row
165 | }
166 |
167 |
168 | internal func btnClick(btn:UIButton) {
169 | if btn.tag == 1 {
170 | if let closure = didConfirmClosure{
171 | closure(self.currentIndex)
172 | }
173 | }
174 |
175 | cover.alpha = 0.021;
176 | UIApplication.shared.keyWindow?.endEditing(true)
177 |
178 | }
179 |
180 | override func layoutSubviews() {
181 | super.layoutSubviews()
182 |
183 | //titleView
184 | setH(256)
185 |
186 | let titleViewX:CGFloat = 0
187 | let titleViewY:CGFloat = 0
188 | let titleViewW:CGFloat = bounds.width
189 | let titleViewH:CGFloat = 50
190 | titleView?.frame = CGRect(x: titleViewX, y: titleViewY, width: titleViewW, height: titleViewH)
191 |
192 | let cancelX:CGFloat = 0
193 | let cancelY:CGFloat = 0
194 | let cancelW:CGFloat = 80
195 | let cancelH:CGFloat = titleViewH
196 | cancelBtn?.frame = CGRect(x: cancelX, y: cancelY, width: cancelW, height: cancelH)
197 |
198 | let confirmW:CGFloat = cancelW
199 | let confirmH:CGFloat = titleViewH
200 | let confirmX:CGFloat = bounds.width - confirmW
201 | let confirmY:CGFloat = 0
202 | confirmBtn?.frame = CGRect(x: confirmX, y: confirmY, width: confirmW, height: confirmH)
203 |
204 | let titleW:CGFloat = bounds.width - cancelW*2
205 | let titleH:CGFloat = titleViewH
206 | let titleX:CGFloat = (cancelBtn?.frame.maxX)!
207 | let titleY:CGFloat = 0
208 | titleLabel?.frame = CGRect(x: titleX, y: titleY, width: titleW, height: titleH)
209 |
210 |
211 | let pickerX:CGFloat = 0
212 | let pickerY:CGFloat = titleViewH
213 | let pickerW:CGFloat = titleViewW
214 | let pickerH:CGFloat = bounds.size.height - titleViewH
215 | pickerView.frame = CGRect(x: pickerX, y: pickerY, width: pickerW, height: pickerH)
216 |
217 | }
218 |
219 | required init?(coder aDecoder: NSCoder) {
220 | fatalError("init(coder:) has not been implemented")
221 | }
222 |
223 |
224 | /**
225 | * 此方法当 自定键盘移动到窗口上调用
226 | */
227 | override func didMoveToWindow() {
228 | super.didMoveToWindow()
229 | if isRemove == false {
230 | let window:UIWindow = UIApplication.shared.keyWindow!
231 | cover.frame = ScreenBounds
232 | cover.alpha = 0.4
233 | window.addSubview(cover)
234 | }else
235 | {
236 | isRemove = false
237 | }
238 | }
239 |
240 |
241 | /**
242 | * 移除时 将蒙板一并移除
243 | */
244 | override func removeFromSuperview() {
245 | isRemove = true
246 | cover.removeFromSuperview()
247 |
248 | super.removeFromSuperview()
249 | }
250 |
251 |
252 | func exitKeyBoard() {
253 | cover.alpha = 0.021
254 | UIApplication.shared.keyWindow?.endEditing(true)
255 | }
256 |
257 | func reloadData() {
258 | self.currentIndex = 0
259 | pickerView.reloadAllComponents()
260 | }
261 | }
262 |
--------------------------------------------------------------------------------
/Demo/JWDatePickerView/JWDatePickerView.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 5BA28ADF1D3DC2F300E4AFEA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5BA28ADE1D3DC2F300E4AFEA /* main.m */; };
11 | 5BA28AE21D3DC2F300E4AFEA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5BA28AE11D3DC2F300E4AFEA /* AppDelegate.m */; };
12 | 5BA28AE51D3DC2F300E4AFEA /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5BA28AE41D3DC2F300E4AFEA /* ViewController.m */; };
13 | 5BA28AE81D3DC2F300E4AFEA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5BA28AE61D3DC2F300E4AFEA /* Main.storyboard */; };
14 | 5BA28AEB1D3DC2F300E4AFEA /* JWDatePickerView.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 5BA28AE91D3DC2F300E4AFEA /* JWDatePickerView.xcdatamodeld */; };
15 | 5BA28AED1D3DC2F300E4AFEA /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5BA28AEC1D3DC2F300E4AFEA /* Assets.xcassets */; };
16 | 5BA28AF01D3DC2F300E4AFEA /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5BA28AEE1D3DC2F300E4AFEA /* LaunchScreen.storyboard */; };
17 | 5BA28AFA1D3DC32A00E4AFEA /* JWDatePickerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5BA28AF91D3DC32A00E4AFEA /* JWDatePickerView.m */; };
18 | 5BA28AFD1D3E10EE00E4AFEA /* KBDatePickerViewkeyBoard.m in Sources */ = {isa = PBXBuildFile; fileRef = 5BA28AFC1D3E10EE00E4AFEA /* KBDatePickerViewkeyBoard.m */; };
19 | /* End PBXBuildFile section */
20 |
21 | /* Begin PBXFileReference section */
22 | 5BA28ADA1D3DC2F300E4AFEA /* JWDatePickerView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JWDatePickerView.app; sourceTree = BUILT_PRODUCTS_DIR; };
23 | 5BA28ADE1D3DC2F300E4AFEA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
24 | 5BA28AE01D3DC2F300E4AFEA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
25 | 5BA28AE11D3DC2F300E4AFEA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
26 | 5BA28AE31D3DC2F300E4AFEA /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
27 | 5BA28AE41D3DC2F300E4AFEA /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
28 | 5BA28AE71D3DC2F300E4AFEA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
29 | 5BA28AEA1D3DC2F300E4AFEA /* JWDatePickerView.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = JWDatePickerView.xcdatamodel; sourceTree = ""; };
30 | 5BA28AEC1D3DC2F300E4AFEA /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
31 | 5BA28AEF1D3DC2F300E4AFEA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
32 | 5BA28AF11D3DC2F300E4AFEA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
33 | 5BA28AF81D3DC32A00E4AFEA /* JWDatePickerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JWDatePickerView.h; sourceTree = ""; };
34 | 5BA28AF91D3DC32A00E4AFEA /* JWDatePickerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JWDatePickerView.m; sourceTree = ""; };
35 | 5BA28AFB1D3E10ED00E4AFEA /* KBDatePickerViewkeyBoard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KBDatePickerViewkeyBoard.h; sourceTree = ""; };
36 | 5BA28AFC1D3E10EE00E4AFEA /* KBDatePickerViewkeyBoard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KBDatePickerViewkeyBoard.m; sourceTree = ""; };
37 | /* End PBXFileReference section */
38 |
39 | /* Begin PBXFrameworksBuildPhase section */
40 | 5BA28AD71D3DC2F300E4AFEA /* Frameworks */ = {
41 | isa = PBXFrameworksBuildPhase;
42 | buildActionMask = 2147483647;
43 | files = (
44 | );
45 | runOnlyForDeploymentPostprocessing = 0;
46 | };
47 | /* End PBXFrameworksBuildPhase section */
48 |
49 | /* Begin PBXGroup section */
50 | 5BA28AD11D3DC2F300E4AFEA = {
51 | isa = PBXGroup;
52 | children = (
53 | 5BA28ADC1D3DC2F300E4AFEA /* JWDatePickerView */,
54 | 5BA28ADB1D3DC2F300E4AFEA /* Products */,
55 | );
56 | sourceTree = "";
57 | };
58 | 5BA28ADB1D3DC2F300E4AFEA /* Products */ = {
59 | isa = PBXGroup;
60 | children = (
61 | 5BA28ADA1D3DC2F300E4AFEA /* JWDatePickerView.app */,
62 | );
63 | name = Products;
64 | sourceTree = "";
65 | };
66 | 5BA28ADC1D3DC2F300E4AFEA /* JWDatePickerView */ = {
67 | isa = PBXGroup;
68 | children = (
69 | 5BA28AF71D3DC2FA00E4AFEA /* JWDatePickerView */,
70 | 5BA28AE01D3DC2F300E4AFEA /* AppDelegate.h */,
71 | 5BA28AE11D3DC2F300E4AFEA /* AppDelegate.m */,
72 | 5BA28AE31D3DC2F300E4AFEA /* ViewController.h */,
73 | 5BA28AE41D3DC2F300E4AFEA /* ViewController.m */,
74 | 5BA28AE61D3DC2F300E4AFEA /* Main.storyboard */,
75 | 5BA28AEC1D3DC2F300E4AFEA /* Assets.xcassets */,
76 | 5BA28AEE1D3DC2F300E4AFEA /* LaunchScreen.storyboard */,
77 | 5BA28AF11D3DC2F300E4AFEA /* Info.plist */,
78 | 5BA28AE91D3DC2F300E4AFEA /* JWDatePickerView.xcdatamodeld */,
79 | 5BA28ADD1D3DC2F300E4AFEA /* Supporting Files */,
80 | );
81 | path = JWDatePickerView;
82 | sourceTree = "";
83 | };
84 | 5BA28ADD1D3DC2F300E4AFEA /* Supporting Files */ = {
85 | isa = PBXGroup;
86 | children = (
87 | 5BA28ADE1D3DC2F300E4AFEA /* main.m */,
88 | );
89 | name = "Supporting Files";
90 | sourceTree = "";
91 | };
92 | 5BA28AF71D3DC2FA00E4AFEA /* JWDatePickerView */ = {
93 | isa = PBXGroup;
94 | children = (
95 | 5BA28AFB1D3E10ED00E4AFEA /* KBDatePickerViewkeyBoard.h */,
96 | 5BA28AFC1D3E10EE00E4AFEA /* KBDatePickerViewkeyBoard.m */,
97 | 5BA28AF81D3DC32A00E4AFEA /* JWDatePickerView.h */,
98 | 5BA28AF91D3DC32A00E4AFEA /* JWDatePickerView.m */,
99 | );
100 | path = JWDatePickerView;
101 | sourceTree = "";
102 | };
103 | /* End PBXGroup section */
104 |
105 | /* Begin PBXNativeTarget section */
106 | 5BA28AD91D3DC2F300E4AFEA /* JWDatePickerView */ = {
107 | isa = PBXNativeTarget;
108 | buildConfigurationList = 5BA28AF41D3DC2F300E4AFEA /* Build configuration list for PBXNativeTarget "JWDatePickerView" */;
109 | buildPhases = (
110 | 5BA28AD61D3DC2F300E4AFEA /* Sources */,
111 | 5BA28AD71D3DC2F300E4AFEA /* Frameworks */,
112 | 5BA28AD81D3DC2F300E4AFEA /* Resources */,
113 | );
114 | buildRules = (
115 | );
116 | dependencies = (
117 | );
118 | name = JWDatePickerView;
119 | productName = JWDatePickerView;
120 | productReference = 5BA28ADA1D3DC2F300E4AFEA /* JWDatePickerView.app */;
121 | productType = "com.apple.product-type.application";
122 | };
123 | /* End PBXNativeTarget section */
124 |
125 | /* Begin PBXProject section */
126 | 5BA28AD21D3DC2F300E4AFEA /* Project object */ = {
127 | isa = PBXProject;
128 | attributes = {
129 | LastUpgradeCheck = 0730;
130 | ORGANIZATIONNAME = zhujianwei;
131 | TargetAttributes = {
132 | 5BA28AD91D3DC2F300E4AFEA = {
133 | CreatedOnToolsVersion = 7.3.1;
134 | DevelopmentTeam = 4575Y5U33P;
135 | };
136 | };
137 | };
138 | buildConfigurationList = 5BA28AD51D3DC2F300E4AFEA /* Build configuration list for PBXProject "JWDatePickerView" */;
139 | compatibilityVersion = "Xcode 3.2";
140 | developmentRegion = English;
141 | hasScannedForEncodings = 0;
142 | knownRegions = (
143 | en,
144 | Base,
145 | );
146 | mainGroup = 5BA28AD11D3DC2F300E4AFEA;
147 | productRefGroup = 5BA28ADB1D3DC2F300E4AFEA /* Products */;
148 | projectDirPath = "";
149 | projectRoot = "";
150 | targets = (
151 | 5BA28AD91D3DC2F300E4AFEA /* JWDatePickerView */,
152 | );
153 | };
154 | /* End PBXProject section */
155 |
156 | /* Begin PBXResourcesBuildPhase section */
157 | 5BA28AD81D3DC2F300E4AFEA /* Resources */ = {
158 | isa = PBXResourcesBuildPhase;
159 | buildActionMask = 2147483647;
160 | files = (
161 | 5BA28AF01D3DC2F300E4AFEA /* LaunchScreen.storyboard in Resources */,
162 | 5BA28AED1D3DC2F300E4AFEA /* Assets.xcassets in Resources */,
163 | 5BA28AE81D3DC2F300E4AFEA /* Main.storyboard in Resources */,
164 | );
165 | runOnlyForDeploymentPostprocessing = 0;
166 | };
167 | /* End PBXResourcesBuildPhase section */
168 |
169 | /* Begin PBXSourcesBuildPhase section */
170 | 5BA28AD61D3DC2F300E4AFEA /* Sources */ = {
171 | isa = PBXSourcesBuildPhase;
172 | buildActionMask = 2147483647;
173 | files = (
174 | 5BA28AE51D3DC2F300E4AFEA /* ViewController.m in Sources */,
175 | 5BA28AFA1D3DC32A00E4AFEA /* JWDatePickerView.m in Sources */,
176 | 5BA28AEB1D3DC2F300E4AFEA /* JWDatePickerView.xcdatamodeld in Sources */,
177 | 5BA28AE21D3DC2F300E4AFEA /* AppDelegate.m in Sources */,
178 | 5BA28AFD1D3E10EE00E4AFEA /* KBDatePickerViewkeyBoard.m in Sources */,
179 | 5BA28ADF1D3DC2F300E4AFEA /* main.m in Sources */,
180 | );
181 | runOnlyForDeploymentPostprocessing = 0;
182 | };
183 | /* End PBXSourcesBuildPhase section */
184 |
185 | /* Begin PBXVariantGroup section */
186 | 5BA28AE61D3DC2F300E4AFEA /* Main.storyboard */ = {
187 | isa = PBXVariantGroup;
188 | children = (
189 | 5BA28AE71D3DC2F300E4AFEA /* Base */,
190 | );
191 | name = Main.storyboard;
192 | sourceTree = "";
193 | };
194 | 5BA28AEE1D3DC2F300E4AFEA /* LaunchScreen.storyboard */ = {
195 | isa = PBXVariantGroup;
196 | children = (
197 | 5BA28AEF1D3DC2F300E4AFEA /* Base */,
198 | );
199 | name = LaunchScreen.storyboard;
200 | sourceTree = "";
201 | };
202 | /* End PBXVariantGroup section */
203 |
204 | /* Begin XCBuildConfiguration section */
205 | 5BA28AF21D3DC2F300E4AFEA /* Debug */ = {
206 | isa = XCBuildConfiguration;
207 | buildSettings = {
208 | ALWAYS_SEARCH_USER_PATHS = NO;
209 | CLANG_ANALYZER_NONNULL = YES;
210 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
211 | CLANG_CXX_LIBRARY = "libc++";
212 | CLANG_ENABLE_MODULES = YES;
213 | CLANG_ENABLE_OBJC_ARC = YES;
214 | CLANG_WARN_BOOL_CONVERSION = YES;
215 | CLANG_WARN_CONSTANT_CONVERSION = YES;
216 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
217 | CLANG_WARN_EMPTY_BODY = YES;
218 | CLANG_WARN_ENUM_CONVERSION = YES;
219 | CLANG_WARN_INT_CONVERSION = YES;
220 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
221 | CLANG_WARN_UNREACHABLE_CODE = YES;
222 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
223 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
224 | COPY_PHASE_STRIP = NO;
225 | DEBUG_INFORMATION_FORMAT = dwarf;
226 | ENABLE_STRICT_OBJC_MSGSEND = YES;
227 | ENABLE_TESTABILITY = YES;
228 | GCC_C_LANGUAGE_STANDARD = gnu99;
229 | GCC_DYNAMIC_NO_PIC = NO;
230 | GCC_NO_COMMON_BLOCKS = YES;
231 | GCC_OPTIMIZATION_LEVEL = 0;
232 | GCC_PREPROCESSOR_DEFINITIONS = (
233 | "DEBUG=1",
234 | "$(inherited)",
235 | );
236 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
237 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
238 | GCC_WARN_UNDECLARED_SELECTOR = YES;
239 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
240 | GCC_WARN_UNUSED_FUNCTION = YES;
241 | GCC_WARN_UNUSED_VARIABLE = YES;
242 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
243 | MTL_ENABLE_DEBUG_INFO = YES;
244 | ONLY_ACTIVE_ARCH = YES;
245 | SDKROOT = iphoneos;
246 | TARGETED_DEVICE_FAMILY = "1,2";
247 | };
248 | name = Debug;
249 | };
250 | 5BA28AF31D3DC2F300E4AFEA /* Release */ = {
251 | isa = XCBuildConfiguration;
252 | buildSettings = {
253 | ALWAYS_SEARCH_USER_PATHS = NO;
254 | CLANG_ANALYZER_NONNULL = YES;
255 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
256 | CLANG_CXX_LIBRARY = "libc++";
257 | CLANG_ENABLE_MODULES = YES;
258 | CLANG_ENABLE_OBJC_ARC = YES;
259 | CLANG_WARN_BOOL_CONVERSION = YES;
260 | CLANG_WARN_CONSTANT_CONVERSION = YES;
261 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
262 | CLANG_WARN_EMPTY_BODY = YES;
263 | CLANG_WARN_ENUM_CONVERSION = YES;
264 | CLANG_WARN_INT_CONVERSION = YES;
265 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
266 | CLANG_WARN_UNREACHABLE_CODE = YES;
267 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
268 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
269 | COPY_PHASE_STRIP = NO;
270 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
271 | ENABLE_NS_ASSERTIONS = NO;
272 | ENABLE_STRICT_OBJC_MSGSEND = YES;
273 | GCC_C_LANGUAGE_STANDARD = gnu99;
274 | GCC_NO_COMMON_BLOCKS = YES;
275 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
276 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
277 | GCC_WARN_UNDECLARED_SELECTOR = YES;
278 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
279 | GCC_WARN_UNUSED_FUNCTION = YES;
280 | GCC_WARN_UNUSED_VARIABLE = YES;
281 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
282 | MTL_ENABLE_DEBUG_INFO = NO;
283 | SDKROOT = iphoneos;
284 | TARGETED_DEVICE_FAMILY = "1,2";
285 | VALIDATE_PRODUCT = YES;
286 | };
287 | name = Release;
288 | };
289 | 5BA28AF51D3DC2F300E4AFEA /* Debug */ = {
290 | isa = XCBuildConfiguration;
291 | buildSettings = {
292 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
293 | CODE_SIGN_IDENTITY = "iPhone Developer";
294 | INFOPLIST_FILE = JWDatePickerView/Info.plist;
295 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
296 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
297 | PRODUCT_BUNDLE_IDENTIFIER = com.zjw.otherApp;
298 | PRODUCT_NAME = "$(TARGET_NAME)";
299 | };
300 | name = Debug;
301 | };
302 | 5BA28AF61D3DC2F300E4AFEA /* Release */ = {
303 | isa = XCBuildConfiguration;
304 | buildSettings = {
305 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
306 | CODE_SIGN_IDENTITY = "iPhone Developer";
307 | INFOPLIST_FILE = JWDatePickerView/Info.plist;
308 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
309 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
310 | PRODUCT_BUNDLE_IDENTIFIER = com.zjw.otherApp;
311 | PRODUCT_NAME = "$(TARGET_NAME)";
312 | };
313 | name = Release;
314 | };
315 | /* End XCBuildConfiguration section */
316 |
317 | /* Begin XCConfigurationList section */
318 | 5BA28AD51D3DC2F300E4AFEA /* Build configuration list for PBXProject "JWDatePickerView" */ = {
319 | isa = XCConfigurationList;
320 | buildConfigurations = (
321 | 5BA28AF21D3DC2F300E4AFEA /* Debug */,
322 | 5BA28AF31D3DC2F300E4AFEA /* Release */,
323 | );
324 | defaultConfigurationIsVisible = 0;
325 | defaultConfigurationName = Release;
326 | };
327 | 5BA28AF41D3DC2F300E4AFEA /* Build configuration list for PBXNativeTarget "JWDatePickerView" */ = {
328 | isa = XCConfigurationList;
329 | buildConfigurations = (
330 | 5BA28AF51D3DC2F300E4AFEA /* Debug */,
331 | 5BA28AF61D3DC2F300E4AFEA /* Release */,
332 | );
333 | defaultConfigurationIsVisible = 0;
334 | defaultConfigurationName = Release;
335 | };
336 | /* End XCConfigurationList section */
337 |
338 | /* Begin XCVersionGroup section */
339 | 5BA28AE91D3DC2F300E4AFEA /* JWDatePickerView.xcdatamodeld */ = {
340 | isa = XCVersionGroup;
341 | children = (
342 | 5BA28AEA1D3DC2F300E4AFEA /* JWDatePickerView.xcdatamodel */,
343 | );
344 | currentVersion = 5BA28AEA1D3DC2F300E4AFEA /* JWDatePickerView.xcdatamodel */;
345 | path = JWDatePickerView.xcdatamodeld;
346 | sourceTree = "";
347 | versionGroupType = wrapper.xcdatamodel;
348 | };
349 | /* End XCVersionGroup section */
350 | };
351 | rootObject = 5BA28AD21D3DC2F300E4AFEA /* Project object */;
352 | }
353 |
--------------------------------------------------------------------------------
/JWDatePickerView/JWDatePickerView.m:
--------------------------------------------------------------------------------
1 | //
2 | // JWDatePickerView.m
3 | // JWDatePickerView
4 | //
5 | // Created by 朱建伟 on 16/7/19.
6 | // Copyright © 2016年 zhujianwei. All rights reserved.
7 | //
8 | #define KSplit @"(#拆#)"//用来拆分
9 |
10 | #define KTotalFormatter @"yyyy MM dd HH mm ss"
11 | #define KTotalFormatterStr @"%@ %@ %@ %@ %@ %@"
12 |
13 | #define KComUnit NSCalendarUnitYear|NSCalendarUnitDay|NSCalendarUnitMonth|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond
14 |
15 |
16 | #import "JWDatePickerView.h"
17 |
18 | @interface JWDatePickerView()
19 | /**
20 | * bgView
21 | */
22 | @property(nonatomic,strong)UIView* bgView;
23 | /**
24 | * pickerView
25 | */
26 | @property(nonatomic,strong)UIPickerView* pickerView;
27 |
28 | /**
29 | * modeDict
30 | */
31 | @property(nonatomic,strong)NSMutableDictionary* modeDict;
32 | /**
33 | * formatterDict
34 | */
35 | @property(nonatomic,strong)NSMutableDictionary* formatterDict;
36 |
37 | /**
38 | * unitdict
39 | */
40 | @property(nonatomic,strong)NSMutableDictionary* unitStrDict;
41 |
42 | /**
43 | * calendar
44 | */
45 | @property(nonatomic,strong)NSCalendar* calendar;
46 |
47 | /**
48 | * dateFormmater
49 | */
50 | @property(nonatomic,strong)NSDateFormatter* dateF;
51 |
52 |
53 | /**
54 | * formmater
55 | */
56 | @property(nonatomic,strong)NSDateFormatter* simpleDateF;
57 |
58 | /**
59 | * tempComps
60 | */
61 | @property(nonatomic,strong)NSDateComponents *tempDateComps;
62 |
63 |
64 | @end
65 |
66 | @implementation JWDatePickerView
67 |
68 | /**
69 | * 初始化控件
70 | */
71 | -(instancetype)initWithFrame:(CGRect)frame
72 | {
73 | if (self = [super initWithFrame:frame]) {
74 | self.minuteSpace = 1;
75 | self.secondSpace = 1;
76 |
77 | self.bgView = [[UIView alloc] init];
78 | [self addSubview:self.bgView];
79 |
80 | //模式
81 | self.pickerMode = JWDatePickerMode_DateAddHour;
82 | self.font = [UIFont boldSystemFontOfSize:16];
83 |
84 | //pickerView
85 | self.pickerView = [[UIPickerView alloc] init];
86 | self.pickerView.backgroundColor = [UIColor whiteColor];
87 | self.pickerView.delegate = self;
88 | self.pickerView.dataSource = self;
89 | [self.bgView addSubview:self.pickerView];
90 |
91 | }
92 | return self;
93 | }
94 |
95 |
96 | - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
97 | {
98 | //返回对应模式下的compsCount
99 | // if (self.pickerMode==JWDatePickerMode_DateAndTime||self.pickerMode==JWDatePickerMode_DateAndTimeRYear||self.pickerMode==JWDatePickerMode_DateAddHour) {
100 | // return 4;
101 | // }else if (self.pickerMode==JWDatePickerMode_TimeRSecond)
102 | // {
103 | // return 2;
104 | // }
105 | // return 3;
106 | return [self.modeDict objectForKey:@(self.pickerMode)].count;
107 | }
108 |
109 |
110 | - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
111 | {
112 | NSArray* groupUnitArray = self.modeDict[@(self.pickerMode)];
113 | if (component>=groupUnitArray.count) {
114 | return 0;
115 | }
116 | NSNumber* number = [groupUnitArray[component] lastObject];
117 |
118 | switch (number.unsignedIntegerValue) {
119 | case NSCalendarUnitYear:
120 | {
121 | NSInteger year= [self.calendar component:number.unsignedIntegerValue fromDate:[self getMaxDate]]-[self.calendar component:number.unsignedIntegerValue fromDate:[self getMinDate]]+1;
122 |
123 |
124 | return year;
125 | break;
126 | }
127 | case NSCalendarUnitMonth:
128 | return 12;
129 | break;
130 | case NSCalendarUnitDay:
131 | {
132 | if (self.pickerMode==JWDatePickerMode_Date||self.pickerMode==JWDatePickerMode_DateAddHour) {//这个模式下 年 月 日 或者 年 月 日 时
133 | //根据年月日刷新 天数
134 | NSInteger days =[self getMonthDaysWithYear:self.tempDateComps.year andMoth:self.tempDateComps.month];
135 | return days;
136 | }else
137 | {
138 |
139 | return [self.calendar components:number.unsignedIntegerValue fromDate:[self getMinDate] toDate:[self getMaxDate] options:NSCalendarMatchLast].day+1;
140 | }
141 | break;
142 | }
143 | case NSCalendarUnitHour:
144 | return 24;
145 | break;
146 |
147 | case NSCalendarUnitMinute:
148 | return 60/self.minuteSpace;
149 | break;
150 |
151 | case NSCalendarUnitSecond:
152 | return 60/self.secondSpace;
153 | break;
154 | default:
155 | break;
156 | }
157 |
158 | return 1;
159 | }
160 |
161 |
162 |
163 | -(NSString*)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
164 | {
165 |
166 |
167 | NSArray* groupUnitArray = self.modeDict[@(self.pickerMode)];
168 |
169 | if (component>=groupUnitArray.count) {
170 | return @"";
171 | }
172 | NSNumber* number = [groupUnitArray[component] lastObject];
173 |
174 | switch (number.unsignedIntegerValue) {
175 | case NSCalendarUnitYear:// 年月日 模式下用
176 | {
177 | NSDateComponents*dateComps = [[NSDateComponents alloc] init];
178 | dateComps.year = row;
179 | NSDate* date = [self.calendar dateByAddingComponents:dateComps toDate:[self getMinDate] options:NSCalendarMatchLast];
180 |
181 | NSArray*dateArray = [[self.dateF stringFromDate:date] componentsSeparatedByString:KSplit];
182 |
183 | return dateArray[component];
184 | break;
185 | }
186 | case NSCalendarUnitMonth://年 月 日 模式下用
187 | {
188 | return [NSString stringWithFormat:@"%02zd%@",row+1,self.unitStrDict[@(NSCalendarUnitMonth)]];
189 | break;
190 | }
191 | case NSCalendarUnitDay:
192 | {
193 | if (self.pickerMode==JWDatePickerMode_Date||self.pickerMode==JWDatePickerMode_DateAddHour) {//这个模式下 单独选择日期
194 | return [NSString stringWithFormat:@"%02zd%@",row+1,self.unitStrDict[@(NSCalendarUnitDay)]];
195 | }else
196 | {
197 | NSDateComponents*dateComps = [[NSDateComponents alloc] init];
198 | dateComps.day = row;
199 | NSDate* date = [self.calendar dateByAddingComponents:dateComps toDate:[self getMinDate] options:NSCalendarMatchLast];
200 |
201 | NSArray*dateArray = [[self.dateF stringFromDate:date] componentsSeparatedByString:KSplit];
202 |
203 | return dateArray[component];
204 | }
205 | break;
206 | }
207 | case NSCalendarUnitHour:
208 | {
209 | return [NSString stringWithFormat:@"%02zd%@",row,self.unitStrDict[@(NSCalendarUnitHour)]];
210 | break;
211 | }
212 | case NSCalendarUnitMinute:
213 | {
214 | return [NSString stringWithFormat:@"%02zd%@",self.minuteSpace*row,self.unitStrDict[@(NSCalendarUnitMinute)]];
215 | break;
216 | }
217 | case NSCalendarUnitSecond:
218 | {
219 | return [NSString stringWithFormat:@"%02zd%@",self.secondSpace*row,self.unitStrDict[@(NSCalendarUnitSecond)]];
220 | break;
221 | }
222 | default:
223 | {
224 | return @"return void";
225 | break;
226 | }
227 | }
228 |
229 | }
230 |
231 | /**
232 | * 选中完日期之后
233 | */
234 | -(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
235 |
236 | //用于拼接日期
237 | __block NSMutableString* m_str = [NSMutableString string];
238 |
239 |
240 | if (self.pickerMode==JWDatePickerMode_DateAndTimeRYear||self.pickerMode==JWDatePickerMode_DateAndTimeRYearAndSecond) {//前面拼 年
241 | //同年可用
242 | NSInteger yearRow = [self.pickerView selectedRowInComponent:0];
243 | NSDateComponents*dateComps = [[NSDateComponents alloc] init];
244 | dateComps.day = yearRow;
245 | NSDate* date = [self.calendar dateByAddingComponents:dateComps toDate:[self getMinDate] options:NSCalendarMatchLast];
246 | NSDateComponents* comps = [self.calendar components:KComUnit fromDate:date];
247 |
248 | [m_str appendFormat:@"%@%@",[NSString stringWithFormat:@"%02zd",comps.year],self.unitStrDict[@(NSCalendarUnitYear)]];
249 | }else if (self.pickerMode == JWDatePickerMode_Time||self.pickerMode==JWDatePickerMode_TimeRSecond)//前面拼接 年月日
250 | {
251 | //同年可用
252 | NSDateComponents* comps = [self.calendar components:KComUnit fromDate:[self getMinDate]];
253 | //yyyy年MM月dd号
254 | [m_str appendFormat:@"%@%@%@%@%@%@%@",[NSString stringWithFormat:@"%02zd",comps.year],self.unitStrDict[@(NSCalendarUnitYear)],[NSString stringWithFormat:@"%02zd",comps.month],self.unitStrDict[@(NSCalendarUnitMonth)],[NSString stringWithFormat:@"%02zd",comps.day],self.unitStrDict[@(NSCalendarUnitDay)],KSplit];
255 | }
256 |
257 | NSArray* groupArray = self.modeDict[@(self.pickerMode)];
258 |
259 |
260 | [groupArray enumerateObjectsUsingBlock:^(NSArray* _Nonnull unitArray, NSUInteger idxOut, BOOL * _Nonnull stop) {
261 | //拼接拆分
262 | if (idxOut!=0) {
263 | [m_str appendString:KSplit];
264 | }
265 | //选择项
266 | NSInteger row = [self.pickerView selectedRowInComponent:idxOut];
267 | NSString *title = [self pickerView:pickerView titleForRow:row forComponent:idxOut];
268 |
269 | if (self.pickerMode==JWDatePickerMode_Date||self.pickerMode==JWDatePickerMode_DateAddHour){
270 | //记录 day 对应的component
271 | if ([unitArray.lastObject unsignedIntegerValue]==NSCalendarUnitYear) {
272 | NSDateComponents*dateComps = [[NSDateComponents alloc] init];
273 | dateComps.year = row;
274 | NSDate* date = [self.calendar dateByAddingComponents:dateComps toDate:[self getMinDate] options:NSCalendarMatchLast];
275 | self.tempDateComps.year = [self.calendar components:KComUnit fromDate:date].year;
276 |
277 | }else if ([unitArray.lastObject unsignedIntegerValue]==NSCalendarUnitMonth)
278 | {
279 |
280 | self.tempDateComps.month = row+1;
281 | }
282 | else if ([unitArray.lastObject unsignedIntegerValue]==NSCalendarUnitDay) {
283 | //获取到当前row 和刷新后的rowCount 比较
284 | NSInteger newRowCount= [self pickerView:pickerView numberOfRowsInComponent:idxOut];
285 | if (row>=newRowCount) {
286 | [self.pickerView selectRow:newRowCount-1 inComponent:idxOut animated:NO];
287 |
288 | title = [NSString stringWithFormat:@"%02zd%@",newRowCount,self.unitStrDict[@(NSCalendarUnitDay)]];
289 | }
290 | [self.pickerView reloadAllComponents];
291 | }
292 | }
293 | [m_str appendString:title];
294 |
295 | }];
296 |
297 |
298 | NSDate* date = [self.simpleDateF dateFromString:m_str];
299 |
300 | if (!date) {
301 | NSLog(@"Date is nil");
302 | return;
303 | }
304 |
305 | if(date){[self checkWithSelectedDate:date];}else{NSLog(@"Date 为 nil");}
306 |
307 |
308 | }
309 |
310 |
311 | /**
312 | * 根据选择的时间 验证最大时间和最小时间 可以择调用回调
313 | */
314 | -(void)checkWithSelectedDate:(NSDate*)date
315 | {
316 | if ([date compare:self.maxDate]==NSOrderedDescending){
317 | _date = self.maxDate;
318 | [self scrollToCurrentDate:self.date animated:YES];
319 | }else if ([date compare:self.minDate]==NSOrderedAscending) {
320 | _date = self.minDate;
321 | [self scrollToCurrentDate:self.date animated:YES];
322 | }else
323 | {
324 | _date = date;
325 | }
326 | }
327 |
328 |
329 | /**
330 | * 四舍五入 date 数据
331 | */
332 | -(NSDate*)getRoundDateWithDate:(NSDate*)date
333 | {
334 | NSDateComponents *com = [self.calendar components:KComUnit fromDate:date];
335 |
336 | NSInteger day = com.day;
337 | NSInteger hour = (com.hour%KHourSpace?com.hour/KHourSpace+1:com.hour/KHourSpace)*KHourSpace;
338 | NSInteger minute = (com.minute%KMinuteSpace?com.minute/KMinuteSpace+1:com.minute/KMinuteSpace)*KMinuteSpace;
339 |
340 |
341 | NSDateComponents* dateAdd = [[NSDateComponents alloc] init];
342 | dateAdd.minute = minute - com.minute;
343 | dateAdd.hour = hour - com.hour;
344 | dateAdd.day = day - com.day;
345 |
346 |
347 | return [self.calendar dateByAddingComponents:dateAdd toDate:date options:0];
348 | }
349 |
350 |
351 |
352 | /**
353 | * 宽度
354 | */
355 | - (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component
356 | {
357 | NSInteger coms = [self numberOfComponentsInPickerView:self.pickerView];
358 | CGFloat width = self.bounds.size.width-(coms-1)*10;
359 |
360 | NSString* formatterStr = [self getDateFormatterWithPickModel:self.pickerMode];
361 | NSArray* array = [formatterStr componentsSeparatedByString:KSplit];
362 |
363 | __block NSUInteger maxLength = 0;
364 | [array enumerateObjectsUsingBlock:^(NSString* _Nonnull str, NSUInteger idx, BOOL * _Nonnull stop) {
365 | maxLength+=str.length;
366 | }];
367 | return width/maxLength*[array[component] length];
368 | }
369 |
370 | /**
371 | * 高度
372 | */
373 | - (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component
374 | {
375 | return (self.bounds.size.height-20)/4;
376 | }
377 |
378 |
379 |
380 |
381 | -(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(nullable UIView *)view
382 | {
383 | UILabel* label = nil;
384 | if (view&&[view isKindOfClass:[UILabel class]]) {
385 | label =(UILabel*)view;
386 | }else
387 | {
388 | label= [[UILabel alloc] init];
389 | label.textAlignment =NSTextAlignmentCenter;
390 | label.font =self.font?self.font:[UIFont systemFontOfSize:16];
391 | }
392 | label.text = [self pickerView:pickerView titleForRow:row forComponent:component];
393 | return label;
394 | }
395 |
396 |
397 |
398 | /**
399 | * 布局
400 | */
401 | -(void)layoutSubviews
402 | {
403 | [super layoutSubviews];
404 |
405 | self.bgView.frame = self.bounds;
406 |
407 | CGFloat pickerX = 0;
408 | CGFloat pickerY = 10;
409 | CGFloat pickerW = self.bounds.size.width;
410 | CGFloat pickerH = self.bounds.size.height-20;
411 | self.pickerView.frame= CGRectMake(pickerX, pickerY, pickerW, pickerH);
412 |
413 | }
414 |
415 |
416 |
417 | /**
418 | * 设置dateFormmater
419 | */
420 | -(NSString*)getDateFormatterWithPickModel:(JWDatePickerMode)mode
421 | {
422 | __block NSMutableString* m_str = [NSMutableString string];
423 |
424 | NSArray* groupArray = self.modeDict[@(mode)];
425 |
426 |
427 | [groupArray enumerateObjectsUsingBlock:^(NSArray* _Nonnull unitArray, NSUInteger idx, BOOL * _Nonnull stop) {
428 | //拼接拆分
429 | if (idx!=0) {
430 | [m_str appendString:KSplit];
431 | }
432 | //遍历模式
433 | [unitArray enumerateObjectsUsingBlock:^(NSNumber* _Nonnull unitNumber, NSUInteger idx, BOOL * _Nonnull stop) {
434 | //拼接日历格式化字符串
435 | [m_str appendString:(self.formatterDict[unitNumber])];
436 |
437 | //拼接单位
438 | if (self.delegate&&[self.delegate respondsToSelector:@selector(datePickerView:unitForCalendarUnit:)]) {
439 | NSString* unitStr = self.unitStrDict[unitNumber];
440 | [m_str appendString:unitStr];
441 | }
442 | }];
443 | }];
444 | return m_str;
445 |
446 | }
447 |
448 |
449 |
450 | /**
451 | * 滚动到指定的位置
452 | */
453 | -(void)reloadDataNeedScrollTo:(BOOL)need
454 | {
455 |
456 | [self.pickerView reloadAllComponents];
457 |
458 |
459 | [self.pickerView setNeedsLayout];
460 |
461 |
462 | if([self getCurrentDate]&&need)//滑动到显示时间
463 | {
464 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
465 | [self scrollToCurrentDate:[self getCurrentDate] animated:YES];
466 | });
467 | }
468 | }
469 |
470 | /**
471 | * 滚动到指定的时间
472 | */
473 | -(void)scrollToCurrentDate:(NSDate*)date animated:(BOOL)animated
474 | {
475 |
476 | NSArray* groupUnitArray = self.modeDict[@(self.pickerMode)];
477 |
478 | [groupUnitArray enumerateObjectsUsingBlock:^(NSArray* _Nonnull unitArray, NSUInteger idx, BOOL * _Nonnull stop) {
479 |
480 | NSNumber *number = unitArray.lastObject;
481 | //获取的对应的组的rowCount
482 | NSInteger maxRowCount = [self pickerView:self.pickerView numberOfRowsInComponent:idx];
483 | //分项处理
484 | switch (number.unsignedIntegerValue) {
485 | case NSCalendarUnitYear:// 年月日 模式下用
486 | {
487 | NSInteger year= [self.calendar component:number.unsignedIntegerValue fromDate:date]-[self.calendar component:number.unsignedIntegerValue fromDate:[self getMinDate]];
488 |
489 | if (year*)modeDict
710 | {
711 | if (_modeDict==nil) {
712 | _modeDict = [NSMutableDictionary dictionary];
713 | // JWDatePickerMode_DateAndTime,// 年月日 时分秒
714 | _modeDict[@(JWDatePickerMode_DateAndTime)]= @[@[@(NSCalendarUnitYear),@(NSCalendarUnitMonth),@(NSCalendarUnitDay)],@[@(NSCalendarUnitHour)],@[@(NSCalendarUnitMinute)],@[@(NSCalendarUnitSecond)]];
715 |
716 | // JWDatePickerMode_Time,// 时分秒
717 | _modeDict[@(JWDatePickerMode_Time)]= @[@[@(NSCalendarUnitHour)],@[@(NSCalendarUnitMinute)],@[@(NSCalendarUnitSecond)]];
718 |
719 |
720 | // JWDatePickerMode_TimeRSecond,// 时分
721 | _modeDict[@(JWDatePickerMode_TimeRSecond)]= @[@[@(NSCalendarUnitHour)],@[@(NSCalendarUnitMinute)]];
722 |
723 | // JWDatePickerMode_Date,// 年月日
724 | _modeDict[@(JWDatePickerMode_Date)]= @[@[@(NSCalendarUnitYear)],@[@(NSCalendarUnitMonth)],@[@(NSCalendarUnitDay)]];
725 |
726 | // JWDatePickerMode_DateAndTimeRYear,// 月日 时 分 秒
727 | _modeDict[@(JWDatePickerMode_DateAndTimeRYear)]= @[@[@(NSCalendarUnitMonth),@(NSCalendarUnitDay)],@[@(NSCalendarUnitHour)],@[@(NSCalendarUnitMinute)],@[@(NSCalendarUnitSecond)]];
728 |
729 | // JWDatePickerMode_DateAddHour,// 年月日 时 分
730 | _modeDict[@(JWDatePickerMode_DateAddHour)]= @[@[@(NSCalendarUnitYear)],@[@(NSCalendarUnitMonth)],@[@(NSCalendarUnitDay)],@[@(NSCalendarUnitHour)]];
731 |
732 | // JWDatePickerMode_DateAndTimeRSecond,// 年月日 时 分
733 | _modeDict[@(JWDatePickerMode_DateAndTimeRSecond)]= @[@[@(NSCalendarUnitYear),@(NSCalendarUnitMonth),@(NSCalendarUnitDay)],@[@(NSCalendarUnitHour)],@[@(NSCalendarUnitMinute)]];
734 |
735 |
736 | // JWDatePickerMode_DateAndTimeRYearAndSecond,//月日 时分
737 | _modeDict[@(JWDatePickerMode_DateAndTimeRYearAndSecond)]= @[@[@(NSCalendarUnitMonth),@(NSCalendarUnitDay)],@[@(NSCalendarUnitHour)],@[@(NSCalendarUnitMinute)]];
738 |
739 | }
740 |
741 | return _modeDict;
742 | }
743 |
744 | /**
745 | * 格式化字符串
746 | */
747 | -(NSDateFormatter *)dateF
748 | {
749 | if (_dateF==nil) {
750 | _dateF = [[NSDateFormatter alloc] init];
751 | }
752 | return _dateF;
753 | }
754 |
755 | -(NSMutableDictionary *)unitStrDict
756 | {
757 | if (_unitStrDict ==nil&&self.delegate) {
758 | _unitStrDict = [NSMutableDictionary dictionary];
759 |
760 | [self.formatterDict enumerateKeysAndObjectsUsingBlock:^(NSNumber* _Nonnull unitNumber, id _Nonnull obj, BOOL * _Nonnull stop) {
761 |
762 | NSString* unitStr = @"";
763 |
764 | if (self.delegate&&[self.delegate respondsToSelector:@selector(datePickerView:unitForCalendarUnit:)]) {
765 | unitStr = [self.delegate datePickerView:self unitForCalendarUnit:unitNumber.unsignedIntegerValue];
766 | //验证拆分
767 | if([unitStr rangeOfString:KSplit].location!=NSNotFound)
768 | {
769 | unitStr = @"";
770 | }
771 | }
772 | _unitStrDict[unitNumber] = unitStr;
773 | }];
774 |
775 | }
776 | return _unitStrDict;
777 | }
778 |
779 | /**
780 | * 格式化
781 | */
782 | -(NSMutableDictionary *)formatterDict
783 | {
784 | if (_formatterDict ==nil) {
785 | _formatterDict = [NSMutableDictionary dictionary];
786 | _formatterDict[@(NSCalendarUnitYear)]= @"yyyy";
787 | _formatterDict[@(NSCalendarUnitMonth)]= @"MM";
788 | _formatterDict[@(NSCalendarUnitDay)]= @"dd";
789 | _formatterDict[@(NSCalendarUnitHour)]= @"HH";
790 | _formatterDict[@(NSCalendarUnitMinute)]= @"mm";
791 | _formatterDict[@(NSCalendarUnitSecond)]= @"ss";
792 | }
793 | return _formatterDict;
794 | }
795 |
796 | /**
797 | * 设置日期格式
798 | */
799 | -(void)setDateFDateFormatter
800 | {
801 | //1.获取到当前模式下的 格式化字符串
802 | NSString *dateFormatterStr = [self getDateFormatterWithPickModel:self.pickerMode];
803 | self.dateF.dateFormat = dateFormatterStr;
804 |
805 | //2.拼接 转换选中模式下的格式化字符串
806 | NSString* sourceFormatter = @"";
807 | if (self.pickerMode==JWDatePickerMode_DateAndTimeRYear||self.pickerMode==JWDatePickerMode_DateAndTimeRYearAndSecond) {//前面拼 年
808 | sourceFormatter = [NSString stringWithFormat:@"yyyy%@",self.unitStrDict[@(NSCalendarUnitYear)]];
809 | }else if (self.pickerMode == JWDatePickerMode_Time||self.pickerMode==JWDatePickerMode_TimeRSecond)//前面拼接 年月日
810 | {
811 | sourceFormatter =[NSString stringWithFormat:@"yyyy%@MM%@dd%@%@",self.unitStrDict[@(NSCalendarUnitYear)],self.unitStrDict[@(NSCalendarUnitMonth)],self.unitStrDict[@(NSCalendarUnitDay)],KSplit];
812 | }
813 |
814 | //3.完整拼接
815 | NSString* lastFormatterStr = [NSString stringWithFormat:@"%@%@",sourceFormatter,dateFormatterStr];
816 |
817 | //4.设置格式化字符串
818 | self.simpleDateF.dateFormat= lastFormatterStr;
819 |
820 | }
821 |
822 |
823 |
824 | /**
825 | * 获取最大时间
826 | */
827 | -(NSDate*)getMinDate
828 | {
829 | if (self.minDate==nil) {
830 |
831 | if (self.maxDate) {//设置 最小日期的时候
832 | if (self.pickerMode==JWDatePickerMode_DateAndTimeRYear||self.pickerMode==JWDatePickerMode_DateAndTimeRYearAndSecond) {//同一年
833 | NSDateComponents *addComps = [[NSDateComponents alloc] init];
834 | addComps.year = -1;
835 | addComps.day = 1;
836 | self.minDate = [self.calendar dateByAddingComponents:addComps toDate:self.maxDate options:NSCalendarMatchLast];
837 | }else if (self.pickerMode==JWDatePickerMode_Time||self.pickerMode==JWDatePickerMode_TimeRSecond)//同一天
838 | {
839 | self.minDate = [self getDayLastDateWithDate:self.maxDate max:NO];
840 | }
841 | else{
842 | NSDateComponents* comps = [[NSDateComponents alloc] init];
843 | comps.year = -1;
844 | self.minDate = [self.calendar dateByAddingComponents:comps toDate:self.maxDate options:NSCalendarMatchLast];
845 | }
846 | }else
847 | {
848 | self.minDate = [NSDate date];
849 | }
850 | }
851 | return self.minDate;
852 | }
853 |
854 | /**
855 | * 获取最小时间
856 | */
857 | -(NSDate*)getMaxDate
858 | {
859 | if (self.maxDate ==nil) {
860 | if (self.pickerMode==JWDatePickerMode_DateAndTimeRYear||self.pickerMode==JWDatePickerMode_DateAndTimeRYearAndSecond) {//同一年
861 | NSDateComponents *addComps = [[NSDateComponents alloc] init];
862 | addComps.year = 1;
863 | addComps.day = -1;
864 | _maxDate = [self.calendar dateByAddingComponents:addComps toDate:[self getMinDate] options:NSCalendarMatchLast];
865 | }else if (self.pickerMode==JWDatePickerMode_Time||self.pickerMode==JWDatePickerMode_TimeRSecond)//同一天
866 | {
867 | _maxDate = [self getDayLastDateWithDate:self.minDate max:YES];
868 | }
869 | else{
870 | NSDateComponents* comps = [[NSDateComponents alloc] init];
871 | comps.year = 1;
872 | _maxDate = [self.calendar dateByAddingComponents:comps toDate:[self getMinDate] options:NSCalendarMatchLast];
873 | }
874 | }
875 | return self.maxDate;
876 | }
877 |
878 | /**
879 | * 获取当前时间
880 | */
881 | -(NSDate*)getCurrentDate
882 | {
883 | if (self.date ==nil) {
884 | self.date = [self getMinDate];
885 | }
886 | return self.date;
887 | }
888 |
889 |
890 |
891 | /**
892 | * 切换模式时刷新
893 | */
894 | -(void)setPickerMode:(JWDatePickerMode)pickerMode
895 | {
896 |
897 | _pickerMode = pickerMode;
898 |
899 |
900 | [self setDateFDateFormatter];
901 |
902 | //年 月 日 单选
903 | if(self.pickerMode==JWDatePickerMode_Date||self.pickerMode==JWDatePickerMode_DateAddHour){
904 | if (!self.date) {
905 | self.date = [self getMinDate];
906 | }
907 | NSDateComponents *comps= [self.calendar components:KComUnit fromDate:self.date];
908 | self.tempDateComps.year=comps.year;
909 | self.tempDateComps.month = comps.month;
910 | }
911 |
912 | if (self.minDate&&self.maxDate) {
913 | if (self.pickerMode==JWDatePickerMode_DateAndTimeRYear||self.pickerMode==JWDatePickerMode_DateAndTimeRYearAndSecond) {//同一年
914 | // 最小时间1年后的时间 compare 最大时间
915 | NSDateComponents *addComps = [[NSDateComponents alloc] init];
916 | addComps.year = 1;
917 | addComps.day = -1;
918 | NSDate* lastMaxDate = [self.calendar dateByAddingComponents:addComps toDate:self.minDate options:NSCalendarMatchLast];
919 | if ([lastMaxDate compare:self.maxDate]==NSOrderedAscending) {
920 |
921 | self.maxDate = lastMaxDate;
922 | [self.pickerView reloadAllComponents];
923 | }
924 | }else if (self.pickerMode==JWDatePickerMode_Time||self.pickerMode==JWDatePickerMode_TimeRSecond)//同一天
925 | {
926 | NSDate* lastMaxDate = [self getDayLastDateWithDate:self.minDate max:YES];
927 |
928 | if ([lastMaxDate compare:self.maxDate]==NSOrderedAscending) {
929 | self.maxDate = lastMaxDate;
930 | [self.pickerView reloadAllComponents];
931 | }
932 | }
933 | }
934 |
935 | [self reloadDataNeedScrollTo:YES];
936 |
937 | }
938 |
939 | /**
940 | * 设置代理是刷新
941 | */
942 | -(void)setDelegate:(id)delegate
943 | {
944 | if (delegate) {
945 | _delegate = delegate;
946 |
947 | [self setDateFDateFormatter];
948 |
949 | [self reloadData];
950 | }
951 | }
952 |
953 | /**
954 | * 用于转换 选择的时间
955 | */
956 | -(NSDateFormatter *)simpleDateF
957 | {
958 | if (_simpleDateF==nil) {
959 | _simpleDateF = [[NSDateFormatter alloc] init];
960 | }
961 | return _simpleDateF;
962 | }
963 |
964 |
965 | /**
966 | * 限制间隔
967 | */
968 | -(void)setMinuteSpace:(NSUInteger)minuteSpace
969 | {
970 | if (minuteSpace<30&&60%minuteSpace==0) {
971 | _minuteSpace = minuteSpace;
972 | }
973 |
974 | }
975 |
976 | /**
977 | * 限制间隔
978 | */
979 | -(void)setSecondSpace:(NSUInteger)secondSpace
980 | {
981 | if (secondSpace<30&&60%secondSpace==0) {
982 | _secondSpace = secondSpace;
983 | }
984 | }
985 |
986 |
987 | /**
988 | * 是否是闰年
989 | */
990 | -(BOOL)isLeapYear:(NSInteger)year
991 | {
992 | if (year%4==0) {
993 | if (year%100==0) {
994 | if (year%400==0) {
995 | return YES;
996 | }
997 | //能被 4 100 整除 不能被400 整除的 不是闰年
998 | return NO;
999 | }
1000 | //能被4整除 不能被100整除的 是闰年
1001 | return YES;
1002 | }
1003 | //不能为4整除 不是闰年
1004 | return NO;
1005 | }
1006 |
1007 | /**
1008 | * 根据对应的年 和月 返回当月对应的天数
1009 | */
1010 | -(NSInteger)getMonthDaysWithYear:(NSInteger)year andMoth:(NSInteger)moth
1011 | {
1012 | // 31 28 31 30 31 30 31 31 30 31 30 31
1013 | NSArray *daysOfMonth=@[@31,@28,@31,@30,@31,@30,@31,@31,@30,@31,@30,@31];
1014 |
1015 | NSUInteger days=[daysOfMonth[moth-1] integerValue];
1016 |
1017 | if (days==28) {
1018 | if ([self isLeapYear:year])days=29;
1019 | }
1020 | return days;
1021 | }
1022 |
1023 | -(NSDateComponents *)tempDateComps
1024 | {
1025 | if (_tempDateComps==nil) {
1026 | _tempDateComps = [[NSDateComponents alloc] init];
1027 | }
1028 | return _tempDateComps;
1029 | }
1030 |
1031 |
1032 | -(NSString *)getDateStrWithDateFormatterString:(NSString *)formatterStr
1033 | {
1034 | if (self.date&&formatterStr&&formatterStr.length) {
1035 |
1036 | }
1037 | return @"格式化字符串不合法";
1038 | }
1039 |
1040 | -(NSString *)getDateStr
1041 | {
1042 | if (self.date) {
1043 | return [[self.simpleDateF stringFromDate:self.date] stringByReplacingOccurrencesOfString:KSplit withString:@""];
1044 | }
1045 | return @"NO Date";
1046 | }
1047 |
1048 | /**
1049 | * 获取一天中的 最小时间 最大时间
1050 | */
1051 | -(NSDate*)getDayLastDateWithDate:(NSDate*)date max:(BOOL)isGetMax
1052 | {
1053 | if (!date) {
1054 | return [NSDate date];
1055 | }
1056 |
1057 | NSDateComponents*dateComps = [self.calendar components:KComUnit fromDate:date];
1058 | NSInteger hour = dateComps.hour;
1059 | NSInteger minute = dateComps.minute;
1060 | NSInteger second = dateComps.second;
1061 |
1062 | NSDateComponents *newDateComp = [NSDateComponents new];
1063 | if (isGetMax) {
1064 | newDateComp.hour = 24-hour-1;
1065 | newDateComp.minute = 60 - minute -1;
1066 | newDateComp.second = 60 - second -1;
1067 | }else
1068 | {
1069 | newDateComp.hour = -hour;
1070 | newDateComp.minute = -minute;
1071 | newDateComp.second = -second;
1072 | }
1073 | NSDate* lastDate = [self.calendar dateByAddingComponents:newDateComp toDate:date options:NSCalendarMatchLast];
1074 | return lastDate;
1075 | }
1076 | @end
1077 |
--------------------------------------------------------------------------------
/Demo/JWDatePickerView/JWDatePickerView/JWDatePickerView/JWDatePickerView.m:
--------------------------------------------------------------------------------
1 | //
2 | // JWDatePickerView.m
3 | // JWDatePickerView
4 | //
5 | // Created by 朱建伟 on 16/7/19.
6 | // Copyright © 2016年 zhujianwei. All rights reserved.
7 | //
8 | #define KSplit @"(#拆#)"//用来拆分
9 |
10 | #define KTotalFormatter @"yyyy MM dd HH mm ss"
11 | #define KTotalFormatterStr @"%@ %@ %@ %@ %@ %@"
12 |
13 | #define KComUnit NSCalendarUnitYear|NSCalendarUnitDay|NSCalendarUnitMonth|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond
14 |
15 |
16 | #import "JWDatePickerView.h"
17 |
18 | @interface JWDatePickerView()
19 | /**
20 | * bgView
21 | */
22 | @property(nonatomic,strong)UIView* bgView;
23 | /**
24 | * pickerView
25 | */
26 | @property(nonatomic,strong)UIPickerView* pickerView;
27 |
28 | /**
29 | * modeDict
30 | */
31 | @property(nonatomic,strong)NSMutableDictionary* modeDict;
32 | /**
33 | * formatterDict
34 | */
35 | @property(nonatomic,strong)NSMutableDictionary* formatterDict;
36 |
37 | /**
38 | * unitdict
39 | */
40 | @property(nonatomic,strong)NSMutableDictionary* unitStrDict;
41 |
42 | /**
43 | * calendar
44 | */
45 | @property(nonatomic,strong)NSCalendar* calendar;
46 |
47 | /**
48 | * dateFormmater
49 | */
50 | @property(nonatomic,strong)NSDateFormatter* dateF;
51 |
52 |
53 | /**
54 | * formmater
55 | */
56 | @property(nonatomic,strong)NSDateFormatter* simpleDateF;
57 |
58 | /**
59 | * tempComps
60 | */
61 | @property(nonatomic,strong)NSDateComponents *tempDateComps;
62 |
63 |
64 | @end
65 |
66 | @implementation JWDatePickerView
67 |
68 | /**
69 | * 初始化控件
70 | */
71 | -(instancetype)initWithFrame:(CGRect)frame
72 | {
73 | if (self = [super initWithFrame:frame]) {
74 | self.minuteSpace = 1;
75 | self.secondSpace = 1;
76 |
77 | self.bgView = [[UIView alloc] init];
78 | [self addSubview:self.bgView];
79 |
80 | //模式
81 | self.pickerMode = JWDatePickerMode_DateAddHour;
82 | self.font = [UIFont boldSystemFontOfSize:16];
83 |
84 | //pickerView
85 | self.pickerView = [[UIPickerView alloc] init];
86 | self.pickerView.backgroundColor = [UIColor whiteColor];
87 | self.pickerView.delegate = self;
88 | self.pickerView.dataSource = self;
89 | [self.bgView addSubview:self.pickerView];
90 |
91 | }
92 | return self;
93 | }
94 |
95 |
96 | - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
97 | {
98 | //返回对应模式下的compsCount
99 | // if (self.pickerMode==JWDatePickerMode_DateAndTime||self.pickerMode==JWDatePickerMode_DateAndTimeRYear||self.pickerMode==JWDatePickerMode_DateAddHour) {
100 | // return 4;
101 | // }else if (self.pickerMode==JWDatePickerMode_TimeRSecond)
102 | // {
103 | // return 2;
104 | // }
105 | // return 3;
106 | return [self.modeDict objectForKey:@(self.pickerMode)].count;
107 | }
108 |
109 |
110 | - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
111 | {
112 | NSArray* groupUnitArray = self.modeDict[@(self.pickerMode)];
113 | if (component>=groupUnitArray.count) {
114 | return 0;
115 | }
116 | NSNumber* number = [groupUnitArray[component] lastObject];
117 |
118 | switch (number.unsignedIntegerValue) {
119 | case NSCalendarUnitYear:
120 | {
121 | NSInteger year= [self.calendar component:number.unsignedIntegerValue fromDate:[self getMaxDate]]-[self.calendar component:number.unsignedIntegerValue fromDate:[self getMinDate]]+1;
122 |
123 |
124 | return year;
125 | break;
126 | }
127 | case NSCalendarUnitMonth:
128 | return 12;
129 | break;
130 | case NSCalendarUnitDay:
131 | {
132 | if (self.pickerMode==JWDatePickerMode_Date||self.pickerMode==JWDatePickerMode_DateAddHour) {//这个模式下 年 月 日 或者 年 月 日 时
133 | //根据年月日刷新 天数
134 | NSInteger days =[self getMonthDaysWithYear:self.tempDateComps.year andMoth:self.tempDateComps.month];
135 | return days;
136 | }else
137 | {
138 |
139 | return [self.calendar components:number.unsignedIntegerValue fromDate:[self getMinDate] toDate:[self getMaxDate] options:NSCalendarMatchLast].day+1;
140 | }
141 | break;
142 | }
143 | case NSCalendarUnitHour:
144 | return 24;
145 | break;
146 |
147 | case NSCalendarUnitMinute:
148 | return 60/self.minuteSpace;
149 | break;
150 |
151 | case NSCalendarUnitSecond:
152 | return 60/self.secondSpace;
153 | break;
154 | default:
155 | break;
156 | }
157 |
158 | return 1;
159 | }
160 |
161 |
162 |
163 | -(NSString*)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
164 | {
165 |
166 |
167 | NSArray* groupUnitArray = self.modeDict[@(self.pickerMode)];
168 |
169 | if (component>=groupUnitArray.count) {
170 | return @"";
171 | }
172 | NSNumber* number = [groupUnitArray[component] lastObject];
173 |
174 | switch (number.unsignedIntegerValue) {
175 | case NSCalendarUnitYear:// 年月日 模式下用
176 | {
177 | NSDateComponents*dateComps = [[NSDateComponents alloc] init];
178 | dateComps.year = row;
179 | NSDate* date = [self.calendar dateByAddingComponents:dateComps toDate:[self getMinDate] options:NSCalendarMatchLast];
180 |
181 | NSArray*dateArray = [[self.dateF stringFromDate:date] componentsSeparatedByString:KSplit];
182 |
183 | return dateArray[component];
184 | break;
185 | }
186 | case NSCalendarUnitMonth://年 月 日 模式下用
187 | {
188 | return [NSString stringWithFormat:@"%02zd%@",row+1,self.unitStrDict[@(NSCalendarUnitMonth)]];
189 | break;
190 | }
191 | case NSCalendarUnitDay:
192 | {
193 | if (self.pickerMode==JWDatePickerMode_Date||self.pickerMode==JWDatePickerMode_DateAddHour) {//这个模式下 单独选择日期
194 | return [NSString stringWithFormat:@"%02zd%@",row+1,self.unitStrDict[@(NSCalendarUnitDay)]];
195 | }else
196 | {
197 | NSDateComponents*dateComps = [[NSDateComponents alloc] init];
198 | dateComps.day = row;
199 | NSDate* date = [self.calendar dateByAddingComponents:dateComps toDate:[self getMinDate] options:NSCalendarMatchLast];
200 |
201 | NSArray*dateArray = [[self.dateF stringFromDate:date] componentsSeparatedByString:KSplit];
202 |
203 | return dateArray[component];
204 | }
205 | break;
206 | }
207 | case NSCalendarUnitHour:
208 | {
209 | return [NSString stringWithFormat:@"%02zd%@",row,self.unitStrDict[@(NSCalendarUnitHour)]];
210 | break;
211 | }
212 | case NSCalendarUnitMinute:
213 | {
214 | return [NSString stringWithFormat:@"%02zd%@",self.minuteSpace*row,self.unitStrDict[@(NSCalendarUnitMinute)]];
215 | break;
216 | }
217 | case NSCalendarUnitSecond:
218 | {
219 | return [NSString stringWithFormat:@"%02zd%@",self.secondSpace*row,self.unitStrDict[@(NSCalendarUnitSecond)]];
220 | break;
221 | }
222 | default:
223 | {
224 | return @"return void";
225 | break;
226 | }
227 | }
228 |
229 | }
230 |
231 | /**
232 | * 选中完日期之后
233 | */
234 | -(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
235 |
236 | //用于拼接日期
237 | __block NSMutableString* m_str = [NSMutableString string];
238 |
239 |
240 | if (self.pickerMode==JWDatePickerMode_DateAndTimeRYear||self.pickerMode==JWDatePickerMode_DateAndTimeRYearAndSecond) {//前面拼 年
241 | //同年可用
242 | NSInteger yearRow = [self.pickerView selectedRowInComponent:0];
243 | NSDateComponents*dateComps = [[NSDateComponents alloc] init];
244 | dateComps.day = yearRow;
245 | NSDate* date = [self.calendar dateByAddingComponents:dateComps toDate:[self getMinDate] options:NSCalendarMatchLast];
246 | NSDateComponents* comps = [self.calendar components:KComUnit fromDate:date];
247 |
248 | [m_str appendFormat:@"%@%@",[NSString stringWithFormat:@"%02zd",comps.year],self.unitStrDict[@(NSCalendarUnitYear)]];
249 | }else if (self.pickerMode == JWDatePickerMode_Time||self.pickerMode==JWDatePickerMode_TimeRSecond)//前面拼接 年月日
250 | {
251 | //同年可用
252 | NSDateComponents* comps = [self.calendar components:KComUnit fromDate:[self getMinDate]];
253 | //yyyy年MM月dd号
254 | [m_str appendFormat:@"%@%@%@%@%@%@%@",[NSString stringWithFormat:@"%02zd",comps.year],self.unitStrDict[@(NSCalendarUnitYear)],[NSString stringWithFormat:@"%02zd",comps.month],self.unitStrDict[@(NSCalendarUnitMonth)],[NSString stringWithFormat:@"%02zd",comps.day],self.unitStrDict[@(NSCalendarUnitDay)],KSplit];
255 | }
256 |
257 | NSArray* groupArray = self.modeDict[@(self.pickerMode)];
258 |
259 |
260 | [groupArray enumerateObjectsUsingBlock:^(NSArray* _Nonnull unitArray, NSUInteger idxOut, BOOL * _Nonnull stop) {
261 | //拼接拆分
262 | if (idxOut!=0) {
263 | [m_str appendString:KSplit];
264 | }
265 | //选择项
266 | NSInteger row = [self.pickerView selectedRowInComponent:idxOut];
267 | NSString *title = [self pickerView:pickerView titleForRow:row forComponent:idxOut];
268 |
269 | if (self.pickerMode==JWDatePickerMode_Date||self.pickerMode==JWDatePickerMode_DateAddHour){
270 | //记录 day 对应的component
271 | if ([unitArray.lastObject unsignedIntegerValue]==NSCalendarUnitYear) {
272 | NSDateComponents*dateComps = [[NSDateComponents alloc] init];
273 | dateComps.year = row;
274 | NSDate* date = [self.calendar dateByAddingComponents:dateComps toDate:[self getMinDate] options:NSCalendarMatchLast];
275 | self.tempDateComps.year = [self.calendar components:KComUnit fromDate:date].year;
276 |
277 | }else if ([unitArray.lastObject unsignedIntegerValue]==NSCalendarUnitMonth)
278 | {
279 |
280 | self.tempDateComps.month = row+1;
281 | }
282 | else if ([unitArray.lastObject unsignedIntegerValue]==NSCalendarUnitDay) {
283 | //获取到当前row 和刷新后的rowCount 比较
284 | NSInteger newRowCount= [self pickerView:pickerView numberOfRowsInComponent:idxOut];
285 | if (row>=newRowCount) {
286 | [self.pickerView selectRow:newRowCount-1 inComponent:idxOut animated:NO];
287 |
288 | title = [NSString stringWithFormat:@"%02zd%@",newRowCount,self.unitStrDict[@(NSCalendarUnitDay)]];
289 | }
290 | [self.pickerView reloadAllComponents];
291 | }
292 | }
293 | [m_str appendString:title];
294 |
295 | }];
296 |
297 |
298 | NSDate* date = [self.simpleDateF dateFromString:m_str];
299 |
300 | if (!date) {
301 | NSLog(@"Date is nil");
302 | return;
303 | }
304 |
305 | if(date){[self checkWithSelectedDate:date];}else{NSLog(@"Date 为 nil");}
306 |
307 |
308 | }
309 |
310 |
311 | /**
312 | * 根据选择的时间 验证最大时间和最小时间 可以择调用回调
313 | */
314 | -(void)checkWithSelectedDate:(NSDate*)date
315 | {
316 | if ([date compare:self.maxDate]==NSOrderedDescending){
317 | _date = self.maxDate;
318 | [self scrollToCurrentDate:self.date animated:YES];
319 | }else if ([date compare:self.minDate]==NSOrderedAscending) {
320 | _date = self.minDate;
321 | [self scrollToCurrentDate:self.date animated:YES];
322 | }else
323 | {
324 | _date = date;
325 | }
326 | }
327 |
328 |
329 | /**
330 | * 四舍五入 date 数据
331 | */
332 | -(NSDate*)getRoundDateWithDate:(NSDate*)date
333 | {
334 | NSDateComponents *com = [self.calendar components:KComUnit fromDate:date];
335 |
336 | NSInteger day = com.day;
337 | NSInteger hour = (com.hour%KHourSpace?com.hour/KHourSpace+1:com.hour/KHourSpace)*KHourSpace;
338 | NSInteger minute = (com.minute%KMinuteSpace?com.minute/KMinuteSpace+1:com.minute/KMinuteSpace)*KMinuteSpace;
339 |
340 |
341 | NSDateComponents* dateAdd = [[NSDateComponents alloc] init];
342 | dateAdd.minute = minute - com.minute;
343 | dateAdd.hour = hour - com.hour;
344 | dateAdd.day = day - com.day;
345 |
346 |
347 | return [self.calendar dateByAddingComponents:dateAdd toDate:date options:0];
348 | }
349 |
350 |
351 |
352 | /**
353 | * 宽度
354 | */
355 | - (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component
356 | {
357 | NSInteger coms = [self numberOfComponentsInPickerView:self.pickerView];
358 | CGFloat width = self.bounds.size.width-(coms-1)*10;
359 |
360 | NSString* formatterStr = [self getDateFormatterWithPickModel:self.pickerMode];
361 | NSArray* array = [formatterStr componentsSeparatedByString:KSplit];
362 |
363 | __block NSUInteger maxLength = 0;
364 | [array enumerateObjectsUsingBlock:^(NSString* _Nonnull str, NSUInteger idx, BOOL * _Nonnull stop) {
365 | maxLength+=str.length;
366 | }];
367 | return width/maxLength*[array[component] length];
368 | }
369 |
370 | /**
371 | * 高度
372 | */
373 | - (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component
374 | {
375 | return (self.bounds.size.height-20)/4;
376 | }
377 |
378 |
379 |
380 |
381 | -(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(nullable UIView *)view
382 | {
383 | UILabel* label = nil;
384 | if (view&&[view isKindOfClass:[UILabel class]]) {
385 | label =(UILabel*)view;
386 | }else
387 | {
388 | label= [[UILabel alloc] init];
389 | label.textAlignment =NSTextAlignmentCenter;
390 | label.font =self.font?self.font:[UIFont systemFontOfSize:16];
391 | }
392 | label.text = [self pickerView:pickerView titleForRow:row forComponent:component];
393 | return label;
394 | }
395 |
396 |
397 |
398 | /**
399 | * 布局
400 | */
401 | -(void)layoutSubviews
402 | {
403 | [super layoutSubviews];
404 |
405 | self.bgView.frame = self.bounds;
406 |
407 | CGFloat pickerX = 0;
408 | CGFloat pickerY = 10;
409 | CGFloat pickerW = self.bounds.size.width;
410 | CGFloat pickerH = self.bounds.size.height-20;
411 | self.pickerView.frame= CGRectMake(pickerX, pickerY, pickerW, pickerH);
412 |
413 | }
414 |
415 |
416 |
417 | /**
418 | * 设置dateFormmater
419 | */
420 | -(NSString*)getDateFormatterWithPickModel:(JWDatePickerMode)mode
421 | {
422 | __block NSMutableString* m_str = [NSMutableString string];
423 |
424 | NSArray* groupArray = self.modeDict[@(mode)];
425 |
426 |
427 | [groupArray enumerateObjectsUsingBlock:^(NSArray* _Nonnull unitArray, NSUInteger idx, BOOL * _Nonnull stop) {
428 | //拼接拆分
429 | if (idx!=0) {
430 | [m_str appendString:KSplit];
431 | }
432 | //遍历模式
433 | [unitArray enumerateObjectsUsingBlock:^(NSNumber* _Nonnull unitNumber, NSUInteger idx, BOOL * _Nonnull stop) {
434 | //拼接日历格式化字符串
435 | [m_str appendString:(self.formatterDict[unitNumber])];
436 |
437 | //拼接单位
438 | if (self.delegate&&[self.delegate respondsToSelector:@selector(datePickerView:unitForCalendarUnit:)]) {
439 | NSString* unitStr = self.unitStrDict[unitNumber];
440 | [m_str appendString:unitStr];
441 | }
442 | }];
443 | }];
444 | return m_str;
445 |
446 | }
447 |
448 |
449 |
450 | /**
451 | * 滚动到指定的位置
452 | */
453 | -(void)reloadDataNeedScrollTo:(BOOL)need
454 | {
455 |
456 | [self.pickerView reloadAllComponents];
457 |
458 |
459 | [self.pickerView setNeedsLayout];
460 |
461 |
462 | if([self getCurrentDate]&&need)//滑动到显示时间
463 | {
464 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
465 | [self scrollToCurrentDate:[self getCurrentDate] animated:YES];
466 | });
467 | }
468 | }
469 |
470 | /**
471 | * 滚动到指定的时间
472 | */
473 | -(void)scrollToCurrentDate:(NSDate*)date animated:(BOOL)animated
474 | {
475 |
476 | NSArray* groupUnitArray = self.modeDict[@(self.pickerMode)];
477 |
478 | [groupUnitArray enumerateObjectsUsingBlock:^(NSArray* _Nonnull unitArray, NSUInteger idx, BOOL * _Nonnull stop) {
479 |
480 | NSNumber *number = unitArray.lastObject;
481 | //获取的对应的组的rowCount
482 | NSInteger maxRowCount = [self pickerView:self.pickerView numberOfRowsInComponent:idx];
483 | //分项处理
484 | switch (number.unsignedIntegerValue) {
485 | case NSCalendarUnitYear:// 年月日 模式下用
486 | {
487 | NSInteger year= [self.calendar component:number.unsignedIntegerValue fromDate:date]-[self.calendar component:number.unsignedIntegerValue fromDate:[self getMinDate]];
488 |
489 | if (year*)modeDict
710 | {
711 | if (_modeDict==nil) {
712 | _modeDict = [NSMutableDictionary dictionary];
713 | // JWDatePickerMode_DateAndTime,// 年月日 时分秒
714 | _modeDict[@(JWDatePickerMode_DateAndTime)]= @[@[@(NSCalendarUnitYear),@(NSCalendarUnitMonth),@(NSCalendarUnitDay)],@[@(NSCalendarUnitHour)],@[@(NSCalendarUnitMinute)],@[@(NSCalendarUnitSecond)]];
715 |
716 | // JWDatePickerMode_Time,// 时分秒
717 | _modeDict[@(JWDatePickerMode_Time)]= @[@[@(NSCalendarUnitHour)],@[@(NSCalendarUnitMinute)],@[@(NSCalendarUnitSecond)]];
718 |
719 |
720 | // JWDatePickerMode_TimeRSecond,// 时分
721 | _modeDict[@(JWDatePickerMode_TimeRSecond)]= @[@[@(NSCalendarUnitHour)],@[@(NSCalendarUnitMinute)]];
722 |
723 | // JWDatePickerMode_Date,// 年月日
724 | _modeDict[@(JWDatePickerMode_Date)]= @[@[@(NSCalendarUnitYear)],@[@(NSCalendarUnitMonth)],@[@(NSCalendarUnitDay)]];
725 |
726 | // JWDatePickerMode_DateAndTimeRYear,// 月日 时 分 秒
727 | _modeDict[@(JWDatePickerMode_DateAndTimeRYear)]= @[@[@(NSCalendarUnitMonth),@(NSCalendarUnitDay)],@[@(NSCalendarUnitHour)],@[@(NSCalendarUnitMinute)],@[@(NSCalendarUnitSecond)]];
728 |
729 | // JWDatePickerMode_DateAddHour,// 年月日 时 分
730 | _modeDict[@(JWDatePickerMode_DateAddHour)]= @[@[@(NSCalendarUnitYear)],@[@(NSCalendarUnitMonth)],@[@(NSCalendarUnitDay)],@[@(NSCalendarUnitHour)]];
731 |
732 | // JWDatePickerMode_DateAndTimeRSecond,// 年月日 时 分
733 | _modeDict[@(JWDatePickerMode_DateAndTimeRSecond)]= @[@[@(NSCalendarUnitYear),@(NSCalendarUnitMonth),@(NSCalendarUnitDay)],@[@(NSCalendarUnitHour)],@[@(NSCalendarUnitMinute)]];
734 |
735 |
736 | // JWDatePickerMode_DateAndTimeRYearAndSecond,//月日 时分
737 | _modeDict[@(JWDatePickerMode_DateAndTimeRYearAndSecond)]= @[@[@(NSCalendarUnitMonth),@(NSCalendarUnitDay)],@[@(NSCalendarUnitHour)],@[@(NSCalendarUnitMinute)]];
738 |
739 | }
740 |
741 | return _modeDict;
742 | }
743 |
744 | /**
745 | * 格式化字符串
746 | */
747 | -(NSDateFormatter *)dateF
748 | {
749 | if (_dateF==nil) {
750 | _dateF = [[NSDateFormatter alloc] init];
751 | }
752 | return _dateF;
753 | }
754 |
755 | -(NSMutableDictionary *)unitStrDict
756 | {
757 | if (_unitStrDict ==nil&&self.delegate) {
758 | _unitStrDict = [NSMutableDictionary dictionary];
759 |
760 | [self.formatterDict enumerateKeysAndObjectsUsingBlock:^(NSNumber* _Nonnull unitNumber, id _Nonnull obj, BOOL * _Nonnull stop) {
761 |
762 | NSString* unitStr = @"";
763 |
764 | if (self.delegate&&[self.delegate respondsToSelector:@selector(datePickerView:unitForCalendarUnit:)]) {
765 | unitStr = [self.delegate datePickerView:self unitForCalendarUnit:unitNumber.unsignedIntegerValue];
766 | //验证拆分
767 | if([unitStr rangeOfString:KSplit].location!=NSNotFound)
768 | {
769 | unitStr = @"";
770 | }
771 | }
772 | _unitStrDict[unitNumber] = unitStr;
773 | }];
774 |
775 | }
776 | return _unitStrDict;
777 | }
778 |
779 | /**
780 | * 格式化
781 | */
782 | -(NSMutableDictionary *)formatterDict
783 | {
784 | if (_formatterDict ==nil) {
785 | _formatterDict = [NSMutableDictionary dictionary];
786 | _formatterDict[@(NSCalendarUnitYear)]= @"yyyy";
787 | _formatterDict[@(NSCalendarUnitMonth)]= @"MM";
788 | _formatterDict[@(NSCalendarUnitDay)]= @"dd";
789 | _formatterDict[@(NSCalendarUnitHour)]= @"HH";
790 | _formatterDict[@(NSCalendarUnitMinute)]= @"mm";
791 | _formatterDict[@(NSCalendarUnitSecond)]= @"ss";
792 | }
793 | return _formatterDict;
794 | }
795 |
796 | /**
797 | * 设置日期格式
798 | */
799 | -(void)setDateFDateFormatter
800 | {
801 | //1.获取到当前模式下的 格式化字符串
802 | NSString *dateFormatterStr = [self getDateFormatterWithPickModel:self.pickerMode];
803 | self.dateF.dateFormat = dateFormatterStr;
804 |
805 | //2.拼接 转换选中模式下的格式化字符串
806 | NSString* sourceFormatter = @"";
807 | if (self.pickerMode==JWDatePickerMode_DateAndTimeRYear||self.pickerMode==JWDatePickerMode_DateAndTimeRYearAndSecond) {//前面拼 年
808 | sourceFormatter = [NSString stringWithFormat:@"yyyy%@",self.unitStrDict[@(NSCalendarUnitYear)]];
809 | }else if (self.pickerMode == JWDatePickerMode_Time||self.pickerMode==JWDatePickerMode_TimeRSecond)//前面拼接 年月日
810 | {
811 | sourceFormatter =[NSString stringWithFormat:@"yyyy%@MM%@dd%@%@",self.unitStrDict[@(NSCalendarUnitYear)],self.unitStrDict[@(NSCalendarUnitMonth)],self.unitStrDict[@(NSCalendarUnitDay)],KSplit];
812 | }
813 |
814 | //3.完整拼接
815 | NSString* lastFormatterStr = [NSString stringWithFormat:@"%@%@",sourceFormatter,dateFormatterStr];
816 |
817 | //4.设置格式化字符串
818 | self.simpleDateF.dateFormat= lastFormatterStr;
819 |
820 | }
821 |
822 |
823 |
824 | /**
825 | * 获取最大时间
826 | */
827 | -(NSDate*)getMinDate
828 | {
829 | if (self.minDate==nil) {
830 |
831 | if (self.maxDate) {//设置 最小日期的时候
832 | if (self.pickerMode==JWDatePickerMode_DateAndTimeRYear||self.pickerMode==JWDatePickerMode_DateAndTimeRYearAndSecond) {//同一年
833 | NSDateComponents *addComps = [[NSDateComponents alloc] init];
834 | addComps.year = -1;
835 | addComps.day = 1;
836 | self.minDate = [self.calendar dateByAddingComponents:addComps toDate:self.maxDate options:NSCalendarMatchLast];
837 | }else if (self.pickerMode==JWDatePickerMode_Time||self.pickerMode==JWDatePickerMode_TimeRSecond)//同一天
838 | {
839 | self.minDate = [self getDayLastDateWithDate:self.maxDate max:NO];
840 | }
841 | else{
842 | NSDateComponents* comps = [[NSDateComponents alloc] init];
843 | comps.year = -1;
844 | self.minDate = [self.calendar dateByAddingComponents:comps toDate:self.maxDate options:NSCalendarMatchLast];
845 | }
846 | }else
847 | {
848 | self.minDate = [NSDate date];
849 | }
850 | }
851 | return self.minDate;
852 | }
853 |
854 | /**
855 | * 获取最小时间
856 | */
857 | -(NSDate*)getMaxDate
858 | {
859 | if (self.maxDate ==nil) {
860 | if (self.pickerMode==JWDatePickerMode_DateAndTimeRYear||self.pickerMode==JWDatePickerMode_DateAndTimeRYearAndSecond) {//同一年
861 | NSDateComponents *addComps = [[NSDateComponents alloc] init];
862 | addComps.year = 1;
863 | addComps.day = -1;
864 | _maxDate = [self.calendar dateByAddingComponents:addComps toDate:[self getMinDate] options:NSCalendarMatchLast];
865 | }else if (self.pickerMode==JWDatePickerMode_Time||self.pickerMode==JWDatePickerMode_TimeRSecond)//同一天
866 | {
867 | _maxDate = [self getDayLastDateWithDate:self.minDate max:YES];
868 | }
869 | else{
870 | NSDateComponents* comps = [[NSDateComponents alloc] init];
871 | comps.year = 1;
872 | _maxDate = [self.calendar dateByAddingComponents:comps toDate:[self getMinDate] options:NSCalendarMatchLast];
873 | }
874 | }
875 | return self.maxDate;
876 | }
877 |
878 | /**
879 | * 获取当前时间
880 | */
881 | -(NSDate*)getCurrentDate
882 | {
883 | if (self.date ==nil) {
884 | self.date = [self getMinDate];
885 | }
886 | return self.date;
887 | }
888 |
889 |
890 |
891 | /**
892 | * 切换模式时刷新
893 | */
894 | -(void)setPickerMode:(JWDatePickerMode)pickerMode
895 | {
896 |
897 | _pickerMode = pickerMode;
898 |
899 |
900 | [self setDateFDateFormatter];
901 |
902 | //年 月 日 单选
903 | if(self.pickerMode==JWDatePickerMode_Date||self.pickerMode==JWDatePickerMode_DateAddHour){
904 | if (!self.date) {
905 | self.date = [self getMinDate];
906 | }
907 | NSDateComponents *comps= [self.calendar components:KComUnit fromDate:self.date];
908 | self.tempDateComps.year=comps.year;
909 | self.tempDateComps.month = comps.month;
910 | }
911 |
912 | if (self.minDate&&self.maxDate) {
913 | if (self.pickerMode==JWDatePickerMode_DateAndTimeRYear||self.pickerMode==JWDatePickerMode_DateAndTimeRYearAndSecond) {//同一年
914 | // 最小时间1年后的时间 compare 最大时间
915 | NSDateComponents *addComps = [[NSDateComponents alloc] init];
916 | addComps.year = 1;
917 | addComps.day = -1;
918 | NSDate* lastMaxDate = [self.calendar dateByAddingComponents:addComps toDate:self.minDate options:NSCalendarMatchLast];
919 | if ([lastMaxDate compare:self.maxDate]==NSOrderedAscending) {
920 |
921 | self.maxDate = lastMaxDate;
922 | [self.pickerView reloadAllComponents];
923 | }
924 | }else if (self.pickerMode==JWDatePickerMode_Time||self.pickerMode==JWDatePickerMode_TimeRSecond)//同一天
925 | {
926 | NSDate* lastMaxDate = [self getDayLastDateWithDate:self.minDate max:YES];
927 |
928 | if ([lastMaxDate compare:self.maxDate]==NSOrderedAscending) {
929 | self.maxDate = lastMaxDate;
930 | [self.pickerView reloadAllComponents];
931 | }
932 | }
933 | }
934 |
935 | [self reloadDataNeedScrollTo:YES];
936 |
937 | }
938 |
939 | /**
940 | * 设置代理是刷新
941 | */
942 | -(void)setDelegate:(id)delegate
943 | {
944 | if (delegate) {
945 | _delegate = delegate;
946 |
947 | [self setDateFDateFormatter];
948 |
949 | [self reloadData];
950 | }
951 | }
952 |
953 | /**
954 | * 用于转换 选择的时间
955 | */
956 | -(NSDateFormatter *)simpleDateF
957 | {
958 | if (_simpleDateF==nil) {
959 | _simpleDateF = [[NSDateFormatter alloc] init];
960 | }
961 | return _simpleDateF;
962 | }
963 |
964 |
965 | /**
966 | * 限制间隔
967 | */
968 | -(void)setMinuteSpace:(NSUInteger)minuteSpace
969 | {
970 | if (minuteSpace<30&&60%minuteSpace==0) {
971 | _minuteSpace = minuteSpace;
972 | }
973 |
974 | }
975 |
976 | /**
977 | * 限制间隔
978 | */
979 | -(void)setSecondSpace:(NSUInteger)secondSpace
980 | {
981 | if (secondSpace<30&&60%secondSpace==0) {
982 | _secondSpace = secondSpace;
983 | }
984 | }
985 |
986 |
987 | /**
988 | * 是否是闰年
989 | */
990 | -(BOOL)isLeapYear:(NSInteger)year
991 | {
992 | if (year%4==0) {
993 | if (year%100==0) {
994 | if (year%400==0) {
995 | return YES;
996 | }
997 | //能被 4 100 整除 不能被400 整除的 不是闰年
998 | return NO;
999 | }
1000 | //能被4整除 不能被100整除的 是闰年
1001 | return YES;
1002 | }
1003 | //不能为4整除 不是闰年
1004 | return NO;
1005 | }
1006 |
1007 | /**
1008 | * 根据对应的年 和月 返回当月对应的天数
1009 | */
1010 | -(NSInteger)getMonthDaysWithYear:(NSInteger)year andMoth:(NSInteger)moth
1011 | {
1012 | // 31 28 31 30 31 30 31 31 30 31 30 31
1013 | NSArray *daysOfMonth=@[@31,@28,@31,@30,@31,@30,@31,@31,@30,@31,@30,@31];
1014 |
1015 | NSUInteger days=[daysOfMonth[moth-1] integerValue];
1016 |
1017 | if (days==28) {
1018 | if ([self isLeapYear:year])days=29;
1019 | }
1020 | return days;
1021 | }
1022 |
1023 | -(NSDateComponents *)tempDateComps
1024 | {
1025 | if (_tempDateComps==nil) {
1026 | _tempDateComps = [[NSDateComponents alloc] init];
1027 | }
1028 | return _tempDateComps;
1029 | }
1030 |
1031 |
1032 | -(NSString *)getDateStrWithDateFormatterString:(NSString *)formatterStr
1033 | {
1034 | if (self.date&&formatterStr&&formatterStr.length) {
1035 |
1036 | }
1037 | return @"格式化字符串不合法";
1038 | }
1039 |
1040 | -(NSString *)getDateStr
1041 | {
1042 | if (self.date) {
1043 | return [[self.simpleDateF stringFromDate:self.date] stringByReplacingOccurrencesOfString:KSplit withString:@""];
1044 | }
1045 | return @"NO Date";
1046 | }
1047 |
1048 | /**
1049 | * 获取一天中的 最小时间 最大时间
1050 | */
1051 | -(NSDate*)getDayLastDateWithDate:(NSDate*)date max:(BOOL)isGetMax
1052 | {
1053 | if (!date) {
1054 | return [NSDate date];
1055 | }
1056 |
1057 | NSDateComponents*dateComps = [self.calendar components:KComUnit fromDate:date];
1058 | NSInteger hour = dateComps.hour;
1059 | NSInteger minute = dateComps.minute;
1060 | NSInteger second = dateComps.second;
1061 |
1062 | NSDateComponents *newDateComp = [NSDateComponents new];
1063 | if (isGetMax) {
1064 | newDateComp.hour = 24-hour-1;
1065 | newDateComp.minute = 60 - minute -1;
1066 | newDateComp.second = 60 - second -1;
1067 | }else
1068 | {
1069 | newDateComp.hour = -hour;
1070 | newDateComp.minute = -minute;
1071 | newDateComp.second = -second;
1072 | }
1073 | NSDate* lastDate = [self.calendar dateByAddingComponents:newDateComp toDate:date options:NSCalendarMatchLast];
1074 | return lastDate;
1075 | }
1076 | @end
1077 |
--------------------------------------------------------------------------------
/JWDatePickerView-Swift/JWDatePickerView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // JWDatePickerView.swift
3 | // CarServer
4 | //
5 | // Created by 朱建伟 on 2016/10/13.
6 | // Copyright © 2016年 zhujianwei. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /*
12 |
13 | 使用方法
14 | pickerMode:JWDatePickerMode? 日期选择模式
15 | minDate:Date? 最小日期
16 | maxDate:Date? 最大日期
17 | date:Date? 当前日期
18 | enableLimited:Bool? 限制滚动区域模式 开启后最大最小日期至少有一个有值时有效
19 | unitStrClosure:((NSCalendar.Unit)-> String)? 获取单位的闭包 例如:年 月 日 时 分 秒
20 | didSelectedDateClosure:((Date)->())? 选中了日期
21 | */
22 |
23 | /*
24 | 时间控件的模式
25 | */
26 | public enum JWDatePickerMode:Int{
27 |
28 | case dateAndTime// 年月日 时 分 秒
29 | case dateAndHour// 年月日 时
30 | case dateAndTimeRYear// 月日 时 分 秒
31 | case time// 时 分 秒
32 | case timeRSecond// 时 分
33 | case date// 年 月 日
34 | case dateAddHour// 年 月 日 时
35 | case dateAndTimeRSecond// 年月日 时 分
36 | case dateAndTimeRYearAndSecond// 月日 时 分 3
37 | case dateAndTimeForAllComponent// 年 月 日 时 分 秒
38 | }
39 |
40 |
41 | //Unit
42 | let UnitYear:NSCalendar.Unit = [.year]
43 | let UnitMonth:NSCalendar.Unit = [.month]
44 | let UnitDay:NSCalendar.Unit = [.day]
45 | let UnitHour:NSCalendar.Unit = [.hour]
46 | let UnitMinute:NSCalendar.Unit = [.minute]
47 | let UnitSecond:NSCalendar.Unit = [.second]
48 | let Option:NSCalendar.Options = NSCalendar.Options(rawValue: 0)
49 |
50 |
51 | class JWDatePickerView: UIView,UIPickerViewDelegate,UIPickerViewDataSource{
52 |
53 |
54 | //MARK:公有方法 和 公有属性
55 |
56 | //获取单位
57 | var unitStrClosure:((NSCalendar.Unit)-> String)?
58 |
59 | //选中日期
60 | var didSelectedDateClosure:((Date)->())?
61 |
62 | //无限滚动的最大范围
63 | private let MaxRangeValue:Int = 88888
64 |
65 | //记录当日期选择模式中 无限滚动选项的当前日期 对应组选项索引
66 | private var currentIndex:Int?
67 |
68 | //是否正在滚动
69 | private var currentOperationComponent:Int = 0
70 |
71 | /**
72 | * 最小日期
73 | */
74 | private var _minDate:Date?
75 | var minDate:Date?{
76 | set{
77 |
78 | if let minD = newValue{
79 | _minDate = newValue
80 | //设置最大日期 如果最小日期比最大日期还要大
81 | if let tempMaxDate = maxDate{
82 | //最小日期 比最大日期大
83 | if minD.compare(tempMaxDate) == ComparisonResult.orderedDescending{
84 | //设置最大日期为最小日期
85 | _maxDate = minD
86 | }else{
87 | //如果是需要限制在短时间内的
88 | let unitSubArray:[UInt] = (pickerModeDict[pickerMode!]?.first!)!
89 | if unitSubArray.first != UnitYear.rawValue && unitSubArray.last == UnitDay.rawValue{
90 | let destinationDate = getDateAddOrReduceYear(date: minD, isAdd: true)
91 |
92 | //如果最大日期超过最小日期一年后的范围
93 | if tempMaxDate.compare(destinationDate) == ComparisonResult.orderedDescending{
94 | _maxDate = destinationDate
95 | }
96 | }
97 | }
98 | }else{//最大日期没有值,如果模式需要限制在一年内
99 | let unitSubArray:[UInt] = (pickerModeDict[pickerMode!]?.first!)!
100 | if unitSubArray.first != UnitYear.rawValue && unitSubArray.last == UnitDay.rawValue{
101 |
102 | //一年后的日期
103 | let destinationDate:Date = self.getDateAddOrReduceYear(date: minD, isAdd: true)
104 | //修改掉
105 | _maxDate = destinationDate
106 | }
107 | }
108 |
109 | //验证当前日期
110 | if let currentDate = self.date{
111 | //判断当前日期是否在范围内
112 |
113 | //当前时间比最小时间
114 | if currentDate.compare(minD) == ComparisonResult.orderedAscending{
115 | _date = minD
116 | }
117 |
118 | //判断最大日期的范围
119 | if let tempMaxDate = maxDate{
120 | if currentDate.compare(tempMaxDate) == ComparisonResult.orderedDescending{//当前时间比最大时间大
121 | _date = tempMaxDate
122 | }
123 | }
124 | }else{
125 | _date = minD
126 | }
127 |
128 | //刷新
129 | toCurentDate(animated: false)
130 | }else
131 | {
132 | _minDate = newValue
133 |
134 | //刷新
135 | toCurentDate(animated: false)
136 | }
137 | }
138 | get{
139 |
140 | if _minDate == nil {
141 |
142 | let unitSubArray:[UInt] = (pickerModeDict[pickerMode!]?.first!)!
143 | if unitSubArray.first != UnitYear.rawValue && unitSubArray.last == UnitDay.rawValue{
144 |
145 | //如果最大日期有值
146 | if let tempMaxDate = _maxDate{
147 | let destinationDate = getDateAddOrReduceYear(date: tempMaxDate, isAdd: false)
148 |
149 | //设置时间
150 | self.minDate = destinationDate
151 | }else{
152 | if let date = self.date{
153 | //判断最小日期是否在一年的范围内
154 | var addComps:DateComponents = DateComponents()
155 |
156 | //闰年
157 | if self.isLeapYear(year: (self.currentDateCompnents?.year)!){
158 | addComps.day = -((366-1)/2)
159 | }else{
160 | addComps.day = -((365-1)/2)
161 | }
162 |
163 | //日期
164 | let lastDate:Date = calendar.date(byAdding: addComps, to:date, options: NSCalendar.Options.matchLast)!
165 |
166 | _minDate = lastDate
167 | }
168 | }
169 | }
170 | }
171 |
172 | return _minDate
173 | }
174 | }
175 |
176 |
177 | /**
178 | * 最大日期
179 | */
180 | private var _maxDate:Date?
181 | var maxDate:Date?
182 | {
183 | set{
184 | if let maxD = newValue{
185 | _maxDate = maxD
186 | //设置最小日期 如果最大日期比最小日期还要小
187 | if let tempMinDate = minDate{
188 | //最大日期 比最小日期小
189 | if maxD.compare(tempMinDate) == ComparisonResult.orderedAscending{
190 | //设置最小日期为最大日期
191 | _minDate = maxD
192 | }else{
193 | //如果是需要限制在短时间内的
194 | let unitSubArray:[UInt] = (pickerModeDict[pickerMode!]?.first!)!
195 | if unitSubArray.first != UnitYear.rawValue && unitSubArray.last == UnitDay.rawValue{
196 | let destinationDate = getDateAddOrReduceYear(date: maxD, isAdd: false)
197 |
198 | //如果最小日期超过最大日期一年后的范围
199 | if tempMinDate.compare(destinationDate) == ComparisonResult.orderedAscending{
200 | _minDate = destinationDate
201 | }
202 | }
203 | }
204 | }else{//最大日期没有值,如果模式需要限制在一年内
205 | let unitSubArray:[UInt] = (pickerModeDict[pickerMode!]?.first!)!
206 | if unitSubArray.first != UnitYear.rawValue && unitSubArray.last == UnitDay.rawValue{
207 |
208 | //一年后的日期
209 | let destinationDate:Date = self.getDateAddOrReduceYear(date: maxD, isAdd: false)
210 | //修改掉
211 | _minDate = destinationDate
212 | }
213 | }
214 |
215 | //验证当前日期
216 | if let currentDate = self.date{
217 | //判断当前日期是否在范围内
218 |
219 | if let tempMinDate = minDate{
220 | //当前时间比最小时间
221 | if currentDate.compare(tempMinDate) == ComparisonResult.orderedAscending{
222 | _date = tempMinDate
223 | }
224 | }
225 |
226 | //判断最大日期的范围
227 | if currentDate.compare(maxD) == ComparisonResult.orderedDescending{//当前时间比最大时间大
228 | _date = maxD
229 | }
230 | }else{
231 | _date = maxD
232 | }
233 |
234 |
235 | //刷新
236 | toCurentDate(animated: false)
237 | }else
238 | {
239 | _maxDate = newValue
240 |
241 | //刷新
242 | toCurentDate(animated: false)
243 | }
244 |
245 | }
246 | get{
247 | if _maxDate == nil {
248 | let unitSubArray:[UInt] = (pickerModeDict[pickerMode!]?.first!)!
249 | if unitSubArray.first != UnitYear.rawValue && unitSubArray.last == UnitDay.rawValue{
250 |
251 | //如果最大日期有值
252 | if let tempMinDate = _minDate{
253 | let destinationDate = getDateAddOrReduceYear(date: tempMinDate, isAdd: true)
254 |
255 | //设置时间
256 | self.maxDate = destinationDate
257 | }else{
258 | if let date = self.date{
259 | //判断最小日期是否在一年的范围内
260 | var addComps:DateComponents = DateComponents()
261 |
262 | //闰年
263 | if self.isLeapYear(year: (self.currentDateCompnents?.year)!){
264 | addComps.day = (366-1)/2
265 | }else{
266 | addComps.day = (365-1)/2
267 | }
268 |
269 | //日期
270 | let lastDate:Date = calendar.date(byAdding: addComps, to:date, options: NSCalendar.Options.matchLast)!
271 |
272 | _maxDate = lastDate
273 | }
274 | }
275 |
276 |
277 | }
278 | }
279 |
280 | return _maxDate
281 | }
282 | }
283 |
284 | /**
285 | * 当前日期
286 | */
287 | private var _date:Date?
288 | var date:Date?
289 | {
290 | set{
291 | if let d = newValue {
292 | if let tempMinD = minDate{
293 | if d.compare(tempMinD) == ComparisonResult.orderedAscending{
294 | print("指定日期不在范围内")
295 | return
296 | }
297 | }
298 | if let tempMaxD = maxDate
299 | {
300 | if d.compare(tempMaxD) == ComparisonResult.orderedDescending{
301 | print("指定日期不在范围内")
302 | return
303 | }
304 | }
305 |
306 |
307 | //设置当前的comps
308 | currentDateCompnents = calendar.components(ComUnit, from: d)
309 | _date = d
310 |
311 | toCurentDate(animated: false)
312 |
313 | //刷新
314 | pickerView.reloadAllComponents()
315 | }else
316 | {
317 | _date = newValue
318 |
319 | pickerView .reloadAllComponents()
320 | }
321 | }
322 | get{
323 | if let d = _date
324 | {
325 | return d
326 | }else
327 | {
328 | _date = Date()
329 |
330 | //设置当前的comps
331 | currentDateCompnents = calendar.components(ComUnit, from: _date!)
332 |
333 | return _date
334 | }
335 | }
336 | }
337 |
338 |
339 | //单位
340 | private var _unitDescDict:[UInt:String]!
341 | private var unitDescDict:[UInt:String]!{
342 | set{
343 | if let dict = newValue {
344 | _unitDescDict = dict
345 | }
346 | }
347 | get{
348 | if _unitDescDict == nil {
349 | _unitDescDict = [UInt:String]()
350 | _unitDescDict[UnitYear.rawValue] = "年"
351 | _unitDescDict[UnitMonth.rawValue] = "月"
352 | _unitDescDict[UnitDay.rawValue] = "日"
353 | _unitDescDict[UnitHour.rawValue] = "时"
354 | _unitDescDict[UnitMinute.rawValue] = "分"
355 | _unitDescDict[UnitSecond.rawValue] = "秒"
356 | }
357 |
358 | return _unitDescDict
359 | }
360 | }
361 |
362 | /**
363 | * pickerModel
364 | */
365 | private var _pickerMode:JWDatePickerMode?
366 | var pickerMode:JWDatePickerMode?{
367 | get{
368 | if _pickerMode == nil
369 | {
370 | _pickerMode = JWDatePickerMode.dateAndTimeForAllComponent
371 |
372 | }
373 |
374 | return _pickerMode
375 | }
376 | set{
377 | if let mode = newValue {
378 | _pickerMode = mode
379 |
380 | pickerView.reloadAllComponents()
381 |
382 | //切换模式必须滚动到指定
383 | toCurentDate(animated: false)
384 | }
385 | }
386 | }
387 |
388 | //用来记录 当前选中的年月
389 | private var tempDateCompnents:DateComponents = DateComponents()
390 |
391 |
392 | //用来记录当前date 的 DateComponents
393 | private var _currentDateCompnents:DateComponents?
394 | var currentDateCompnents:DateComponents?{
395 | set{
396 | if let comps = newValue
397 | {
398 | _currentDateCompnents = comps
399 | }else
400 | {
401 | _currentDateCompnents = newValue//可能为nil
402 | }
403 | }
404 | get {
405 |
406 | //如果等于 nil 去获取
407 | if _currentDateCompnents == nil {
408 | //设置当前的comps
409 | _currentDateCompnents = calendar.components(ComUnit, from: date!)
410 | }
411 | return _currentDateCompnents
412 | }
413 | }
414 |
415 | //滚动到指定的日期
416 | func scrollToDate(date:Date?,animated:Bool)
417 | {
418 |
419 | if let d = date {
420 | //赋值私有属性
421 | _date = d
422 |
423 | //设置当前的comps
424 | currentDateCompnents = calendar.components(ComUnit, from: d)
425 |
426 | toCurentDate(animated: animated)
427 | }
428 | }
429 |
430 |
431 | /**
432 | * 是否是闰年
433 | */
434 | func isLeapYear(year:Int) -> Bool {
435 | if (year%4==0) {
436 | if (year%100==0) {
437 | if (year%400==0) {
438 | return true
439 | }
440 | //能被 4 100 整除 不能被400 整除的 不是闰年
441 | return false
442 | }
443 | //能被4整除 不能被100整除的 是闰年
444 | return true
445 | }
446 | //不能为4整除 不是闰年
447 | return false
448 |
449 | }
450 |
451 | /**
452 | * 根据对应的年 和月 返回当月对应的天数
453 | */
454 | func numberOfDaysInMonth(year:Int,month:Int) -> Int {
455 | // 31 28 31 30 31 30 31 31 30 31 30 31
456 | let daysOfMonth:[Int] = [31,28,31,30,31,30,31,31,30,31,30,31]
457 |
458 | let index:Int = (month - 1)
459 | var days:Int = daysOfMonth[index]
460 |
461 | if (days == 28) {
462 | if (isLeapYear(year: year)){
463 | days = 29
464 | }
465 | }
466 | return days
467 |
468 | }
469 |
470 | /**
471 | * 获取一天中的 最小时间 最大时间
472 | */
473 | func dayFirstOrLastDate(date:Date,isLast:Bool) -> Date {
474 | let dateComps:DateComponents = calendar.components(ComUnit, from: date)
475 | let hour:Int = dateComps.hour!
476 | let minute:Int = dateComps.minute!
477 | let second:Int = dateComps.second!
478 |
479 | var newDateComps:DateComponents = DateComponents()
480 | if (isLast) {
481 | newDateComps.hour = 24 - hour - 1;
482 | newDateComps.minute = 60 - minute - 1
483 | newDateComps.second = 60 - second - 1
484 | }else
485 | {
486 | newDateComps.hour = -hour;
487 | newDateComps.minute = -minute;
488 | newDateComps.second = -second;
489 | }
490 |
491 | let d:Date = calendar.date(byAdding: newDateComps, to: date, options: NSCalendar.Options.matchLast)!
492 | return d
493 |
494 | }
495 |
496 |
497 |
498 | //MARK:私有属性
499 |
500 | //开启后 如果 最大日期 或者 最小日期有值 则单向或者双向有限制 否则无效 默认不开启限制
501 | private var _enableLimited:Bool?
502 | var enableLimited:Bool?{
503 | set{
504 | if let enable = newValue{
505 | _enableLimited = enable
506 |
507 | pickerView.reloadAllComponents()
508 |
509 | //刷新时间
510 | toCurentDate(animated: true)
511 | }
512 | }
513 | get{
514 | if let enable = _enableLimited{
515 | return enable
516 | }else
517 | {
518 | return false
519 | }
520 | }
521 | }
522 |
523 |
524 | //comUnit
525 | private let ComUnit:NSCalendar.Unit = [.year,.day,.month,.hour,.minute,.second]
526 |
527 | //记录 当前日期选中
528 | private var sourceCompnentRowDict:[Int:Int] = [Int:Int]()
529 |
530 | //Calendar
531 | private let calendar:NSCalendar = NSCalendar(calendarIdentifier: NSCalendar.Identifier.gregorian)!//NSCalendar(identifier: Calendar.Identifier.gregorian)
532 |
533 | //MARK:控件
534 |
535 | /**
536 | * pickerView
537 | */
538 | private var pickerView:UIPickerView = UIPickerView()
539 |
540 |
541 | //日期选择控件模式
542 | private var pickerModeDict:[JWDatePickerMode:[[UInt]]] = {
543 | var pickerMode:[JWDatePickerMode:[[UInt]]] = [JWDatePickerMode:[[UInt]]]()
544 |
545 | // 年月日 时 分 秒
546 | pickerMode[.dateAndTime] = [[UnitYear.rawValue,UnitMonth.rawValue,UnitDay.rawValue],[UnitHour.rawValue],[UnitMinute.rawValue],[UnitSecond.rawValue]]
547 |
548 | // 月日 时 分 秒
549 | pickerMode[.dateAndTimeRYear] = [[UnitMonth.rawValue,UnitDay.rawValue],[UnitHour.rawValue],[UnitMinute.rawValue],[UnitSecond.rawValue]]
550 |
551 | // 年月日 时
552 | pickerMode[.dateAndHour] = [[UnitYear.rawValue,UnitMonth.rawValue,UnitDay.rawValue],[UnitHour.rawValue]]
553 |
554 |
555 | // 时分秒
556 | pickerMode[.time] = [[UnitHour.rawValue],[UnitMinute.rawValue],[UnitSecond.rawValue]]
557 |
558 | //时分
559 | pickerMode[.timeRSecond] = [[UnitHour.rawValue],[UnitMinute.rawValue]]
560 |
561 | // 年月日
562 | pickerMode[.date] = [[UnitYear.rawValue],[UnitMonth.rawValue],[UnitDay.rawValue]]
563 |
564 | // 年 月 日 时
565 | pickerMode[.dateAddHour] = [[UnitYear.rawValue,UnitMonth.rawValue,UnitDay.rawValue],[UnitHour.rawValue]]
566 |
567 | // 年月日 时 分
568 | pickerMode[.dateAndTimeRSecond] = [[UnitYear.rawValue,UnitMonth.rawValue,UnitDay.rawValue],[UnitHour.rawValue],[UnitMinute.rawValue]]
569 |
570 | //月日 时 分
571 | pickerMode[.dateAndTimeRYearAndSecond] = [[UnitMonth.rawValue,UnitDay.rawValue],[UnitHour.rawValue],[UnitMinute.rawValue],[UnitSecond.rawValue]]
572 |
573 | //年 月 日 时 分 秒
574 | pickerMode[.dateAndTimeForAllComponent] = [[UnitYear.rawValue],[UnitMonth.rawValue],[UnitDay.rawValue],[UnitHour.rawValue],[UnitMinute.rawValue],[UnitSecond.rawValue]]
575 |
576 | return pickerMode
577 | }()
578 |
579 | //初始化
580 | override init(frame: CGRect) {
581 | super.init(frame: frame)
582 |
583 | addSubview(pickerView)
584 |
585 | currentIndex = MaxRangeValue/2
586 |
587 | pickerView.dataSource = self
588 |
589 | //跳到当前日期
590 | toCurentDate(animated: false)
591 |
592 | pickerView.delegate = self
593 |
594 | }
595 |
596 | required init?(coder aDecoder: NSCoder) {
597 | fatalError("init(coder:) has not been implemented")
598 | }
599 |
600 |
601 | //MARK:pickerView代理和数据源
602 | internal func numberOfComponents(in pickerView: UIPickerView) -> Int {
603 |
604 | //1.获取当前模式
605 | let unitArray:[[UInt]] = pickerModeDict[pickerMode!]!
606 |
607 | //2.返回该模式下的components
608 | return unitArray.count
609 | }
610 |
611 |
612 | internal func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
613 | //1.获取当前模式
614 | let unitArray:[[UInt]] = pickerModeDict[pickerMode!]!
615 | //2.判断类型
616 |
617 | var rows = 1
618 |
619 | let unitSubArray:[UInt] = unitArray[component]
620 |
621 | let unit:UInt = unitSubArray.last!
622 |
623 | //3.分类型处理
624 | switch unit {
625 | case UnitYear.rawValue:
626 | //判断限制模式
627 | if limitedEnable() {
628 | //开启了限制返回数据源
629 | rows = numberOfRowsInComponetForLimited(component: component,unit: unit)
630 | }else
631 | {
632 | rows = MaxRangeValue
633 | }
634 | break
635 | case UnitMonth.rawValue:
636 | //判断限制模式
637 | if limitedEnable() {
638 | //开启了限制返回数据源
639 | rows = numberOfRowsInComponetForLimited(component: component,unit: unit)
640 | }else{
641 | //默认12
642 | rows = 12
643 | //第一组的最后一个是 month
644 | if component == 0 {
645 | rows = MaxRangeValue
646 | }
647 | }
648 | break
649 | case UnitDay.rawValue:
650 | //判断限制模式
651 | if limitedEnable() {
652 | //开启了限制返回数据源
653 | rows = numberOfRowsInComponetForLimited(component: component,unit: unit)
654 | }else{
655 | //第一组的最后一个是 days
656 | if component == 0 {
657 | rows = MaxRangeValue
658 | if unitSubArray.first != UnitYear.rawValue && unitSubArray.last == UnitDay.rawValue{//如果第一个是月份
659 | if isLeapYear(year: (currentDateCompnents?.year)!) {
660 | rows = 366-1
661 | }else{
662 | rows = 355-1
663 | }
664 | }
665 | }else//不是第一组 说明需要考虑 选完月份后 该月的天数问题
666 | {
667 | rows = numberOfDaysInMonth(year:tempDateCompnents.year!, month: tempDateCompnents.month!)
668 | }
669 | }
670 | break
671 | case UnitHour.rawValue:
672 | rows = 24//无论是否开启 数据源 公用
673 | break
674 | case UnitMinute.rawValue:
675 | rows = 60
676 | break
677 | case UnitSecond.rawValue:
678 | rows = 60
679 | break
680 | default:
681 |
682 | break
683 | }
684 | return rows
685 | }
686 |
687 |
688 | //获取标题
689 | internal func pickerViewTitle(forRow row:Int,forComponent component:Int) -> String {
690 |
691 | self.currentOperationComponent = component
692 |
693 | //1.计算增量
694 | var addComps:DateComponents = DateComponents()
695 |
696 | //2.获取当前模式
697 | let unitArray:[[UInt]] = pickerModeDict[pickerMode!]!
698 | let unitSubArray:[UInt] = unitArray[component]
699 | let unit:UInt = unitSubArray.last!
700 |
701 |
702 | //3.判断是否第一组
703 | if component == 0 {
704 | //计算偏差
705 | switch unit {
706 | case UnitYear.rawValue:
707 | addComps.year = row - sourceCompnentRowDict[component]!
708 | break
709 | case UnitMonth.rawValue:
710 | addComps.month = row - sourceCompnentRowDict[component]!
711 | break
712 | case UnitDay.rawValue:
713 | addComps.day = row - sourceCompnentRowDict[component]!
714 | break
715 | default:
716 | //剩下的时分秒
717 | return String(format:"%02zd%@",row,unitDescDict[unit]!)
718 | // break
719 | }
720 |
721 |
722 | let tempDate:Date? = calendar.date(byAdding: addComps, to: date!)
723 |
724 | if let tDate:Date = tempDate {
725 | let dateComps:DateComponents = calendar.components(ComUnit, from: tDate)
726 |
727 | return getTitle(comps: dateComps, component:component)
728 | }else
729 | {
730 | return "title nil"
731 | }
732 | }else
733 | {
734 | if unit == UnitMonth.rawValue || unit == UnitDay.rawValue{
735 | return String(format:"%02zd%@",row+1,unitDescDict[unit]!)
736 | }else{
737 | return String(format:"%02zd%@",row,unitDescDict[unit]!)
738 | }
739 |
740 | }
741 | }
742 |
743 |
744 |
745 | internal func pickerView(_ pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat {
746 | //1.获取当前模式
747 | let unitArray:[[UInt]] = pickerModeDict[pickerMode!]!
748 |
749 | //2.计算全部的个数
750 | var totalCount:Int = 0
751 | var totalComponentCount:Int = 0
752 |
753 | var tempComponent = 0
754 | for unitSubArray:[UInt] in unitArray{
755 | for unit:UInt in unitSubArray {
756 | var add:Int = (1 + ( unitDescDict[unit]?.characters.count)!)
757 | // 年的话,加位
758 | if unit == UnitYear.rawValue {
759 | add += 1
760 | }
761 | //计算总长
762 | totalCount += add
763 | //计算当前
764 | if tempComponent == component {
765 | totalComponentCount += add
766 | }
767 | }
768 | tempComponent += 1
769 | }
770 |
771 | //3.更合理的划分
772 | let width:CGFloat = (pickerView.bounds.width - 20.0)
773 | let baseWidth:CGFloat = width/CGFloat(unitArray.count)
774 | let mutiWidth:CGFloat = width - baseWidth
775 |
776 | //4.计算宽度
777 | let componentWidth:CGFloat = CGFloat(totalComponentCount)/CGFloat(totalCount)*mutiWidth + (baseWidth/CGFloat(unitArray.count))
778 |
779 | return componentWidth
780 |
781 | }
782 |
783 | //返回选项高度
784 | internal func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
785 | return pickerView.bounds.height/5
786 | }
787 |
788 |
789 | //返回label
790 | internal func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
791 |
792 | let title:String = pickerViewTitle(forRow: row, forComponent: component)
793 |
794 | var label:UILabel? = nil
795 |
796 | if view != nil {
797 | label = view as! UILabel?
798 | }else{
799 | label = UILabel()
800 | label?.textAlignment = NSTextAlignment.center
801 | // Font_120_218_317_416_515_614_712_810_908
802 | label?.font = Font4
803 | label?.text = title
804 | }
805 | return label!
806 | }
807 |
808 |
809 | //选择停止
810 | func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
811 |
812 | //优化掉
813 | if self.currentOperationComponent != component{
814 | return
815 | }
816 |
817 | //1.获取当前模式
818 | let unitArray:[[UInt]] = pickerModeDict[pickerMode!]!
819 |
820 | //2.遍历 每一组最后一个
821 | var tempComponent:Int = 0
822 |
823 | //用来加减
824 | var addDateComps:DateComponents = DateComponents()
825 |
826 | for unitSubArray:[UInt] in unitArray
827 | {
828 | //当前选中
829 | var currentRow:Int = pickerView.selectedRow(inComponent: tempComponent)
830 | if component == tempComponent {
831 | currentRow = row
832 | }
833 | //单位
834 | let unit:UInt = unitSubArray.last!
835 |
836 |
837 | //分类型处理
838 | switch unit {
839 | case UnitYear.rawValue:
840 | addDateComps.year = currentRow - sourceCompnentRowDict[tempComponent]!
841 | break
842 | case UnitMonth.rawValue:
843 | addDateComps.month = currentRow - sourceCompnentRowDict[tempComponent]!
844 | break
845 | case UnitDay.rawValue:
846 | //如果不是第一组才需要验证
847 | if tempComponent != 0 {
848 | //验证日期 因为每一月的天数不一样
849 | //1.第一步先计算当前步骤选中的年月
850 | let tempDate:Date? = calendar.date(byAdding: addDateComps, to: self.date!, options: NSCalendar.Options.matchLast)
851 | let tempDateComps:DateComponents = calendar.components(ComUnit, from: tempDate!)
852 | tempDateCompnents.year = tempDateComps.year
853 | tempDateCompnents.month = tempDateComps.month
854 | //2.获取天数
855 | let days:Int = numberOfDaysInMonth(year: tempDateComps.year!, month: tempDateComps.month!)
856 | //3.判断当前选择项是否越界
857 | if currentRow > days - 1 {//假如目前为 12月 则 31天 索引 30 ,当选择至11月 则 30天 索引 29 若日期为 12月31 则选择回11月30,最大索引变为29 但当前索引为30 则会越界
858 |
859 | //先选回29再刷新 防止越界闪退
860 | pickerView.selectRow(days - 1, inComponent: tempComponent, animated: false)
861 |
862 | //更新掉 sourceCompentRowDict 和 currentRow
863 | currentRow = days - 1
864 | }
865 | //刷新月份coponent 不同的月份天数不同 随时更新
866 | pickerView.reloadComponent(tempComponent)
867 | }
868 |
869 | //计算时间
870 | addDateComps.day = currentRow - sourceCompnentRowDict[tempComponent]!
871 | break
872 | case UnitHour.rawValue:
873 | addDateComps.hour = currentRow - sourceCompnentRowDict[tempComponent]!
874 | break
875 | case UnitMinute.rawValue:
876 | addDateComps.minute = currentRow - sourceCompnentRowDict[tempComponent]!
877 | break
878 | case UnitSecond.rawValue:
879 | addDateComps.second = currentRow - sourceCompnentRowDict[tempComponent]!
880 | break
881 | default:
882 |
883 | break
884 | }
885 | tempComponent += 1
886 | }
887 |
888 | let date:Date? = calendar.date(byAdding: addDateComps, to: self.date!, options: NSCalendar.Options.matchLast)
889 | if let d = date {
890 |
891 | //标记
892 | var compareFlag:Bool = true
893 |
894 | //如果存在最小的时间
895 | if let minD:Date = minDate {
896 | //当前日期小于最小日期
897 | if(d.compare(minD) == ComparisonResult.orderedAscending){
898 | if let closure = didSelectedDateClosure
899 | {
900 | closure(minD)
901 | }
902 | scrollToDate(date: minD, animated: true)
903 | compareFlag = false
904 | }
905 | }
906 |
907 | //如果存在最大时间
908 | if let maxD:Date = maxDate {
909 | //当前日期大于当前日期
910 | if(d.compare(maxD) == ComparisonResult.orderedDescending){
911 | if let closure = didSelectedDateClosure
912 | {
913 | closure(maxD)
914 | }
915 | scrollToDate(date: maxD, animated: true)
916 | compareFlag = false
917 | }
918 | }
919 |
920 | //日期已定
921 | if compareFlag
922 | {
923 | //如果未开启限制模式,则自动滚动 无限滚动
924 |
925 | scrollToDate(date: d, animated: false)
926 | if let closure = didSelectedDateClosure
927 | {
928 | closure(d)
929 | }
930 | }
931 | }
932 | }
933 |
934 |
935 | //滚动到指定页
936 | internal func toCurentDate(animated:Bool) {
937 |
938 | tempDateCompnents.year = currentDateCompnents?.year
939 | tempDateCompnents.month = currentDateCompnents?.month
940 |
941 | //1.获取当前模式
942 | let unitArray:[[UInt]] = pickerModeDict[pickerMode!]!
943 |
944 | //2.设置选中
945 | var comps:DateComponents = currentDateCompnents!
946 |
947 | //3.分类型处理
948 | var component:Int = 0
949 | var tempRow:Int = 0
950 | for unitSubArray:[UInt] in unitArray{
951 | let unit:UInt = unitSubArray.last!
952 |
953 | switch unit {
954 | case UnitYear.rawValue:
955 | //判断限制模式
956 | if limitedEnable() {
957 | //开启了限制返回数据源
958 | tempRow = selectedRowInComponentForLimited(component: component, unit: unit)
959 | }else{
960 | //第一组的最后一个是 year
961 | tempRow = currentIndex!
962 | }
963 | break
964 | case UnitMonth.rawValue:
965 | //判断限制模式
966 | if limitedEnable() {
967 | //开启了限制返回数据源
968 | tempRow = selectedRowInComponentForLimited(component: component, unit: unit)
969 | }else{
970 | if component == 0 {
971 | //第一组的最后一个是 month
972 | tempRow = currentIndex!
973 | }else
974 | {
975 | //指向 month
976 | tempRow = comps.month!-1
977 | }
978 | }
979 | break
980 | case UnitDay.rawValue:
981 | //判断限制模式
982 | if limitedEnable() {
983 | //开启了限制返回数据源
984 | tempRow = selectedRowInComponentForLimited(component: component, unit: unit)
985 | }else{
986 | if component == 0{
987 | if unitSubArray.first != UnitYear.rawValue && unitSubArray.last == UnitDay.rawValue {//如果第一个是月份 即不是年
988 | if isLeapYear(year: (currentDateCompnents?.year)!) {
989 | //第一组的最后一个是 Day
990 | tempRow = (366-1)/2-1
991 | }else{
992 | //第一组的最后一个是 Day
993 | tempRow = (365-1)/2-1
994 | }
995 | }else{
996 | //第一组的最后一个是 Day
997 | tempRow = currentIndex!
998 | }
999 | }else
1000 | {
1001 | //指向 day
1002 | tempRow = comps.day! - 1
1003 | }
1004 | }
1005 | break
1006 | case UnitHour.rawValue:
1007 | //判断限制模式
1008 | if limitedEnable() {
1009 | //开启了限制返回数据源
1010 | tempRow = selectedRowInComponentForLimited(component: component, unit: unit)
1011 | }else{
1012 | //指向 hour
1013 | tempRow = comps.hour!
1014 | }
1015 | break
1016 | case UnitMinute.rawValue:
1017 | //判断限制模式
1018 | if limitedEnable() {
1019 | //开启了限制返回数据源
1020 | tempRow = selectedRowInComponentForLimited(component: component, unit: unit)
1021 | }else{
1022 | //指向 minute
1023 | tempRow = comps.minute!
1024 | }
1025 | break
1026 | case UnitSecond.rawValue:
1027 | //判断限制模式
1028 | if limitedEnable() {
1029 | //开启了限制返回数据源
1030 | tempRow = selectedRowInComponentForLimited(component: component, unit: unit)
1031 | }else{
1032 | //指向 second
1033 | tempRow = comps.second!
1034 | }
1035 | break
1036 | default:
1037 | //
1038 | break
1039 | }
1040 |
1041 | //滑动到指定选项
1042 | pickerView.selectRow(tempRow, inComponent: component, animated:
1043 | animated)
1044 | //存储
1045 | sourceCompnentRowDict[component] = tempRow
1046 |
1047 | component += 1
1048 |
1049 |
1050 | }
1051 | pickerView.reloadAllComponents()
1052 | }
1053 |
1054 | //布局
1055 | override func layoutSubviews() {
1056 | super.layoutSubviews()
1057 |
1058 | let pickerX:CGFloat = 0
1059 | let pickerY:CGFloat = 0
1060 | let pickerW:CGFloat = bounds.width
1061 | let pickerH:CGFloat = bounds.height
1062 | pickerView.frame = CGRect(x: pickerX, y: pickerY, width: pickerW, height: pickerH)
1063 | }
1064 |
1065 |
1066 | //获取标题
1067 | internal func getTitle(comps:DateComponents,component:Int) -> String
1068 | {
1069 | var m_str:String = String()
1070 |
1071 | //1.获取当前模式
1072 | let unitArray:[[UInt]] = pickerModeDict[pickerMode!]!
1073 | let subArray:[UInt] = unitArray[component]
1074 |
1075 | for unit:UInt in subArray{
1076 | //分类型处理
1077 | switch unit {
1078 | case UnitYear.rawValue:
1079 | m_str.append(String(format: "%04zd%@", comps.year!,unitDescDict[unit]!))
1080 | break
1081 | case UnitMonth.rawValue:
1082 | m_str.append(String(format: "%02zd%@", comps.month!,unitDescDict[unit]!))
1083 | break
1084 | case UnitDay.rawValue:
1085 | m_str.append(String(format: "%02zd%@", comps.day!,unitDescDict[unit]!))
1086 | break
1087 | case UnitHour.rawValue:
1088 | m_str.append(String(format: "%02zd%@", comps.hour!,unitDescDict[unit]!))
1089 | break
1090 | case UnitMinute.rawValue:
1091 | m_str.append(String(format: "%02zd%@", comps.minute!,unitDescDict[unit]!))
1092 | break
1093 | case UnitSecond.rawValue:
1094 | m_str.append(String(format: "%02zd%@", comps.second!,unitDescDict[unit]!))
1095 | break
1096 | default:
1097 |
1098 | break
1099 | }
1100 | }
1101 | return m_str
1102 | }
1103 |
1104 |
1105 | //MARK:用于开始限制功能部分
1106 |
1107 | //获取限制状态
1108 | internal func limitedEnable() -> Bool {
1109 |
1110 | //如果未开启
1111 | if(!enableLimited!)
1112 | {
1113 | let unitSubArray:[UInt] = (pickerModeDict[pickerMode!]?.first!)!
1114 | if unitSubArray.first != UnitYear.rawValue && unitSubArray.last == UnitDay.rawValue{
1115 | return true
1116 | }
1117 | }
1118 | //默认
1119 | return enableLimited!
1120 |
1121 | }
1122 |
1123 | //限制情况下的 数据源
1124 | internal func numberOfRowsInComponetForLimited(component:Int,unit:UInt) -> Int {
1125 | //当前情况下表示第一个
1126 | let minD:Date? = minDate
1127 | //当前情况下表示第一个
1128 | let maxD:Date? = maxDate
1129 |
1130 | var numberOfRows = 0
1131 |
1132 | //分类型处理
1133 | switch unit {
1134 | case UnitYear.rawValue:
1135 | if minD != nil && maxD != nil {//都有值
1136 | numberOfRows = calendar.components(UnitYear, from: getDateRemoveStopLastUnit(date: minD!, lastUnit:UnitYear ,isFromDate: true), to: getDateRemoveStopLastUnit(date: maxD!, lastUnit:UnitYear,isFromDate: false), options: NSCalendar.Options.matchLast).year!+1
1137 | }else{
1138 | numberOfRows = MaxRangeValue
1139 | }
1140 | break
1141 | case UnitMonth.rawValue:
1142 | if component == 0 {
1143 | if minD != nil && maxD != nil {//都有值
1144 | numberOfRows = calendar.components(UnitMonth, from: getDateRemoveStopLastUnit(date: minD!, lastUnit:UnitYear,isFromDate: true), to: getDateRemoveStopLastUnit(date: maxD!, lastUnit:UnitYear,isFromDate: false), options: NSCalendar.Options.matchLast).month!
1145 | }else{
1146 | numberOfRows = MaxRangeValue
1147 | }
1148 | }else
1149 | {
1150 | numberOfRows = 12
1151 | }
1152 | break
1153 | case UnitDay.rawValue:
1154 | if component == 0 {
1155 | if minD != nil && maxD != nil {//都有值
1156 | numberOfRows = calendar.components(UnitDay, from: getDateRemoveStopLastUnit(date: minD!, lastUnit:UnitDay,isFromDate: true), to: getDateRemoveStopLastUnit(date: maxD!, lastUnit:UnitDay,isFromDate: false), options: NSCalendar.Options.matchLast).day!+1
1157 | }else if minD == nil && maxD == nil {
1158 | let comps:DateComponents = calendar.components(ComUnit, from: minD!)
1159 | if isLeapYear(year: (comps.year!)) {
1160 | numberOfRows = 366-1
1161 | }else
1162 | {
1163 | numberOfRows = 365-1
1164 | }
1165 | }else if minD != nil{//只有最小日期
1166 | let comps:DateComponents = calendar.components(ComUnit, from: minD!)
1167 | if isLeapYear(year: (comps.year!)) {
1168 | numberOfRows = 366-1
1169 | }else
1170 | {
1171 | numberOfRows = 365-1
1172 | }
1173 | }else if maxD != nil{
1174 | let comps:DateComponents = calendar.components(ComUnit, from: maxD!)
1175 | if isLeapYear(year: (comps.year!)) {
1176 | numberOfRows = 366
1177 | }else
1178 | {
1179 | numberOfRows = 365
1180 | }
1181 | }
1182 | }else
1183 | {
1184 | numberOfRows = numberOfDaysInMonth(year:tempDateCompnents.year!, month: tempDateCompnents.month!)
1185 | }
1186 | break
1187 | case UnitHour.rawValue:
1188 | numberOfRows = 24
1189 | break
1190 | case UnitMinute.rawValue:
1191 | numberOfRows = 60
1192 | break
1193 | case UnitSecond.rawValue:
1194 | numberOfRows = 60
1195 | break
1196 | default:
1197 |
1198 | break
1199 | }
1200 | return numberOfRows
1201 | }
1202 |
1203 | //选中row
1204 | internal func selectedRowInComponentForLimited(component:Int,unit:UInt) -> Int {
1205 |
1206 | //当前情况下表示第一个
1207 | let minD:Date? = minDate
1208 | //当前情况下表示第一个
1209 | let maxD:Date? = maxDate
1210 |
1211 | var selectedRows:Int = 0
1212 |
1213 | //分类型处理
1214 | switch unit {
1215 | case UnitYear.rawValue:
1216 | if minD != nil{//都有值
1217 | selectedRows = calendar.components(UnitYear, from: getDateRemoveStopLastUnit(date: minD!, lastUnit: UnitYear,isFromDate: true), to: getDateRemoveStopLastUnit(date: date!, lastUnit: UnitYear,isFromDate: false), options: NSCalendar.Options.matchLast).year!
1218 | }else if maxD != nil {
1219 | selectedRows = MaxRangeValue - calendar.components(UnitYear, from: getDateRemoveStopLastUnit(date: date!, lastUnit: UnitYear,isFromDate: true), to: getDateRemoveStopLastUnit(date: maxD!, lastUnit: UnitYear,isFromDate: false), options: NSCalendar.Options.matchLast).year!
1220 | }else if minD != nil && maxD != nil{
1221 | selectedRows = calendar.components(UnitYear, from: getDateRemoveStopLastUnit(date: minD!, lastUnit: UnitYear,isFromDate: true), to: getDateRemoveStopLastUnit(date: date!, lastUnit: UnitYear,isFromDate: false), options: NSCalendar.Options.matchLast).year!
1222 | }
1223 | break
1224 | case UnitMonth.rawValue:
1225 | if component == 0 {
1226 | if minD != nil && maxD != nil {//都有值
1227 | selectedRows = calendar.components(UnitMonth, from: getDateRemoveStopLastUnit(date: minD!, lastUnit: UnitMonth,isFromDate: true), to:getDateRemoveStopLastUnit(date: maxD!, lastUnit: UnitMonth,isFromDate: false), options: NSCalendar.Options.matchLast).month!
1228 | }else if minD == nil && maxD == nil {
1229 | selectedRows = currentIndex!
1230 | }else if minD != nil{
1231 | selectedRows = calendar.components(UnitMonth, from: getDateRemoveStopLastUnit(date: minD!, lastUnit: UnitMonth,isFromDate: true), to: getDateRemoveStopLastUnit(date: maxD!, lastUnit: UnitMonth,isFromDate: false), options: NSCalendar.Options.matchLast).month!
1232 | }else if maxD != nil{
1233 | selectedRows = MaxRangeValue - calendar.components(UnitMonth, from: getDateRemoveStopLastUnit(date: date!, lastUnit: UnitMonth,isFromDate: true), to: getDateRemoveStopLastUnit(date: maxD!, lastUnit: UnitMonth,isFromDate: false), options: NSCalendar.Options.matchLast).month!
1234 | }
1235 | }else
1236 | {
1237 | if minD != nil && maxD != nil{
1238 | selectedRows = (currentDateCompnents?.month)! - 1
1239 | }else{
1240 | selectedRows = currentIndex!
1241 | }
1242 | }
1243 | break
1244 | case UnitDay.rawValue:
1245 | if component == 0 {
1246 | if minD != nil && maxD != nil {//都有值
1247 | selectedRows = calendar.components(UnitDay, from: getDateRemoveStopLastUnit(date: minD!, lastUnit: UnitDay,isFromDate: true), to: getDateRemoveStopLastUnit(date: date!, lastUnit: UnitDay,isFromDate: false), options: NSCalendar.Options.matchLast).day!
1248 | }else if minD == nil && maxD == nil {
1249 | let comps:DateComponents = calendar.components(ComUnit, from: minD!)
1250 |
1251 | if isLeapYear(year: (comps.year!)) {
1252 | selectedRows = (366-1)/2
1253 | }else
1254 | {
1255 | selectedRows = (365-1)/2
1256 | }
1257 | }else if minD != nil{
1258 | selectedRows = calendar.components(UnitDay, from: getDateRemoveStopLastUnit(date: minD!, lastUnit: UnitDay,isFromDate: true), to: getDateRemoveStopLastUnit(date: date!, lastUnit: UnitDay,isFromDate: false), options: NSCalendar.Options.matchLast).day!
1259 |
1260 | }else if maxD != nil{
1261 | let comps:DateComponents = calendar.components(ComUnit, from: maxD!)
1262 | if isLeapYear(year: (comps.year!)) {
1263 |
1264 | selectedRows = 366 - 1 - calendar.components(UnitDay, from: getDateRemoveStopLastUnit(date: date!, lastUnit: UnitDay,isFromDate: true), to: getDateRemoveStopLastUnit(date: maxD!, lastUnit: UnitDay,isFromDate: false), options:Option).day!
1265 | }else
1266 | {
1267 | selectedRows = 365 - 1 - calendar.components(UnitDay, from: getDateRemoveStopLastUnit(date: date!, lastUnit: UnitDay,isFromDate: true), to: getDateRemoveStopLastUnit(date: maxD!, lastUnit: UnitDay,isFromDate: false), options:Option).day!
1268 | }
1269 | }
1270 | }else
1271 | {
1272 | selectedRows = (currentDateCompnents?.day!)!-1//索引
1273 | }
1274 | break
1275 | case UnitHour.rawValue:
1276 | selectedRows = (currentDateCompnents?.hour!)!
1277 | break
1278 | case UnitMinute.rawValue:
1279 | selectedRows = (currentDateCompnents?.minute!)!
1280 | break
1281 | case UnitSecond.rawValue:
1282 | selectedRows = (currentDateCompnents?.second!)!
1283 | break
1284 | default:
1285 |
1286 | break
1287 | }
1288 | return selectedRows
1289 | }
1290 |
1291 |
1292 | //获取一个日期 对应的 前后一年内人的日期
1293 | private func getDateAddOrReduceYear(date:Date,isAdd:Bool) -> Date {
1294 | //判断最小日期是否在一年的范围内
1295 | var addComps:DateComponents = DateComponents()
1296 | if isAdd{
1297 | addComps.year = 1
1298 | addComps.day = -1
1299 | }else{
1300 | addComps.year = -1
1301 | addComps.day = 1
1302 | }
1303 | //日期
1304 | let lastDate:Date = calendar.date(byAdding: addComps, to:date, options: NSCalendar.Options.matchLast)!
1305 |
1306 | return lastDate
1307 | }
1308 |
1309 |
1310 | //去掉多余的日期部分,保证计算日期的差的准确度
1311 | func getDateRemoveStopLastUnit(date:Date,lastUnit:NSCalendar.Unit,isFromDate:Bool) -> Date {
1312 | //初始化
1313 | let unitArray:[UInt] = [UnitYear.rawValue,UnitMonth.rawValue,UnitDay.rawValue,UnitHour.rawValue,UnitMinute.rawValue,UnitSecond.rawValue]
1314 |
1315 | let dateComps:DateComponents = self.calendar.components(ComUnit, from: date)
1316 |
1317 |
1318 | var flag:Bool = true
1319 | var addDateComps:DateComponents = DateComponents()
1320 |
1321 | //遍历
1322 | for unitRawValue in unitArray{
1323 | switch unitRawValue {
1324 | case UnitYear.rawValue:
1325 | if flag {
1326 | addDateComps.year = 0
1327 | }else{
1328 | addDateComps.year = -(dateComps.year)!
1329 | }
1330 | //判断
1331 | if unitRawValue == lastUnit.rawValue{
1332 | flag = false
1333 | }
1334 | break
1335 | case UnitMonth.rawValue:
1336 | if flag {
1337 | addDateComps.month = 0
1338 | }else{
1339 | addDateComps.month = -(dateComps.month)!
1340 | }
1341 | //判断
1342 | if unitRawValue == lastUnit.rawValue{
1343 | flag = false
1344 | }
1345 | break
1346 | case UnitDay.rawValue:
1347 | if flag {
1348 | addDateComps.day = 0
1349 | }else{
1350 | addDateComps.day = -(dateComps.day)!
1351 | }
1352 | //判断
1353 | if unitRawValue == lastUnit.rawValue{
1354 | flag = false
1355 | }
1356 | break
1357 | case UnitHour.rawValue:
1358 | if flag {
1359 | addDateComps.hour = 0
1360 | }else{
1361 | addDateComps.hour = -(dateComps.hour)!
1362 | }
1363 | //判断
1364 | if unitRawValue == lastUnit.rawValue{
1365 | flag = false
1366 | }
1367 | break
1368 | case UnitMinute.rawValue:
1369 | if flag {
1370 | addDateComps.minute = 0
1371 | }else{
1372 | addDateComps.minute = -(dateComps.minute)!
1373 | }
1374 | //判断
1375 | if unitRawValue == lastUnit.rawValue{
1376 | flag = false
1377 | }
1378 | break
1379 | case UnitSecond.rawValue:
1380 | if flag {
1381 | addDateComps.second = 0
1382 | }else{
1383 | addDateComps.second = -(dateComps.second)!
1384 | }
1385 | //判断
1386 | if unitRawValue == lastUnit.rawValue{
1387 | flag = false
1388 | }
1389 | break
1390 | default:
1391 | break
1392 | }
1393 | }
1394 |
1395 | if !isFromDate{
1396 | addDateComps.second = 1
1397 | }
1398 |
1399 | let lastDate:Date = self.calendar.date(byAdding: addDateComps, to: date, options: NSCalendar.Options.matchLast)!
1400 |
1401 | return lastDate
1402 | }
1403 | }
1404 |
--------------------------------------------------------------------------------