├── QFDatePickerView.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ ├── iosyf-02.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ └── liyiping.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ ├── iosyf-02.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ └── xcschememanagement.plist │ ├── jianxuntong.xcuserdatad │ └── xcschemes │ │ ├── QFDatePickerView.xcscheme │ │ └── xcschememanagement.plist │ └── liyiping.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ └── xcschememanagement.plist ├── QFDatePickerView ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ └── LaunchScreen.storyboard ├── Info.plist ├── Main.storyboard ├── QFDatePickerView │ ├── QFDatePickerView.h │ └── QFDatePickerView.m ├── QFTimePickerView │ ├── QFTimePickerView.h │ └── QFTimePickerView.m ├── QFTimerPicker │ ├── Model │ │ ├── QFDateModel.h │ │ ├── QFDateModel.m │ │ ├── QFHourModel.h │ │ ├── QFHourModel.m │ │ ├── QFMinuteModel.h │ │ ├── QFMinuteModel.m │ │ ├── QFTimerDataSourceModel.h │ │ └── QFTimerDataSourceModel.m │ ├── QFTimerPicker │ │ ├── QFTimerPicker.h │ │ └── QFTimerPicker.m │ └── Uitils │ │ ├── QFTimerUtil.h │ │ └── QFTimerUtil.m ├── ViewController.h ├── ViewController.m └── main.m ├── QFDatePickerViewTests ├── Info.plist └── QFDatePickerViewTests.m ├── QFDatePickerViewUITests ├── Info.plist └── QFDatePickerViewUITests.m └── README.md /QFDatePickerView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 851DDD7E1FBA935F007C1E1F /* QFTimePickerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 851DDD7D1FBA935F007C1E1F /* QFTimePickerView.m */; }; 11 | BB39514D1E288B8E000EBDD6 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = BB39514C1E288B8E000EBDD6 /* main.m */; }; 12 | BB3951501E288B8E000EBDD6 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = BB39514F1E288B8E000EBDD6 /* AppDelegate.m */; }; 13 | BB3951581E288B8E000EBDD6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BB3951571E288B8E000EBDD6 /* Assets.xcassets */; }; 14 | BB39515B1E288B8E000EBDD6 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BB3951591E288B8E000EBDD6 /* LaunchScreen.storyboard */; }; 15 | BB3951661E288B8F000EBDD6 /* QFDatePickerViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = BB3951651E288B8F000EBDD6 /* QFDatePickerViewTests.m */; }; 16 | BB3951711E288B8F000EBDD6 /* QFDatePickerViewUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = BB3951701E288B8F000EBDD6 /* QFDatePickerViewUITests.m */; }; 17 | BB39517F1E288B9C000EBDD6 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BB39517E1E288B9C000EBDD6 /* Main.storyboard */; }; 18 | BB3951821E288BAB000EBDD6 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BB3951811E288BAB000EBDD6 /* ViewController.m */; }; 19 | BB3951861E288BDA000EBDD6 /* QFDatePickerView.m in Sources */ = {isa = PBXBuildFile; fileRef = BB3951851E288BDA000EBDD6 /* QFDatePickerView.m */; }; 20 | FD3907F221A29BB900A215CD /* QFTimerPicker.m in Sources */ = {isa = PBXBuildFile; fileRef = FD3907E721A29BB900A215CD /* QFTimerPicker.m */; }; 21 | FD3907F321A29BB900A215CD /* QFTimerUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = FD3907E921A29BB900A215CD /* QFTimerUtil.m */; }; 22 | FDE2217021A7982E0050521D /* QFTimerDataSourceModel.m in Sources */ = {isa = PBXBuildFile; fileRef = FDE2216F21A7982E0050521D /* QFTimerDataSourceModel.m */; }; 23 | FDE2217721A79BD00050521D /* QFDateModel.m in Sources */ = {isa = PBXBuildFile; fileRef = FDE2217121A79BD00050521D /* QFDateModel.m */; }; 24 | FDE2217821A79BD00050521D /* QFMinuteModel.m in Sources */ = {isa = PBXBuildFile; fileRef = FDE2217221A79BD00050521D /* QFMinuteModel.m */; }; 25 | FDE2217921A79BD00050521D /* QFHourModel.m in Sources */ = {isa = PBXBuildFile; fileRef = FDE2217621A79BD00050521D /* QFHourModel.m */; }; 26 | /* End PBXBuildFile section */ 27 | 28 | /* Begin PBXContainerItemProxy section */ 29 | BB3951621E288B8F000EBDD6 /* PBXContainerItemProxy */ = { 30 | isa = PBXContainerItemProxy; 31 | containerPortal = BB3951401E288B8E000EBDD6 /* Project object */; 32 | proxyType = 1; 33 | remoteGlobalIDString = BB3951471E288B8E000EBDD6; 34 | remoteInfo = QFDatePickerView; 35 | }; 36 | BB39516D1E288B8F000EBDD6 /* PBXContainerItemProxy */ = { 37 | isa = PBXContainerItemProxy; 38 | containerPortal = BB3951401E288B8E000EBDD6 /* Project object */; 39 | proxyType = 1; 40 | remoteGlobalIDString = BB3951471E288B8E000EBDD6; 41 | remoteInfo = QFDatePickerView; 42 | }; 43 | /* End PBXContainerItemProxy section */ 44 | 45 | /* Begin PBXFileReference section */ 46 | 851DDD7C1FBA935F007C1E1F /* QFTimePickerView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = QFTimePickerView.h; sourceTree = ""; }; 47 | 851DDD7D1FBA935F007C1E1F /* QFTimePickerView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = QFTimePickerView.m; sourceTree = ""; }; 48 | BB3951481E288B8E000EBDD6 /* QFDatePickerView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = QFDatePickerView.app; sourceTree = BUILT_PRODUCTS_DIR; }; 49 | BB39514C1E288B8E000EBDD6 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 50 | BB39514E1E288B8E000EBDD6 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 51 | BB39514F1E288B8E000EBDD6 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 52 | BB3951571E288B8E000EBDD6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 53 | BB39515A1E288B8E000EBDD6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 54 | BB39515C1E288B8E000EBDD6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 55 | BB3951611E288B8F000EBDD6 /* QFDatePickerViewTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = QFDatePickerViewTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 56 | BB3951651E288B8F000EBDD6 /* QFDatePickerViewTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = QFDatePickerViewTests.m; sourceTree = ""; }; 57 | BB3951671E288B8F000EBDD6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 58 | BB39516C1E288B8F000EBDD6 /* QFDatePickerViewUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = QFDatePickerViewUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 59 | BB3951701E288B8F000EBDD6 /* QFDatePickerViewUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = QFDatePickerViewUITests.m; sourceTree = ""; }; 60 | BB3951721E288B8F000EBDD6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 61 | BB39517E1E288B9C000EBDD6 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; 62 | BB3951801E288BAB000EBDD6 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 63 | BB3951811E288BAB000EBDD6 /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 64 | BB3951841E288BDA000EBDD6 /* QFDatePickerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QFDatePickerView.h; sourceTree = ""; }; 65 | BB3951851E288BDA000EBDD6 /* QFDatePickerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QFDatePickerView.m; sourceTree = ""; }; 66 | FD3907E621A29BB900A215CD /* QFTimerPicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QFTimerPicker.h; sourceTree = ""; }; 67 | FD3907E721A29BB900A215CD /* QFTimerPicker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QFTimerPicker.m; sourceTree = ""; }; 68 | FD3907E921A29BB900A215CD /* QFTimerUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QFTimerUtil.m; sourceTree = ""; }; 69 | FD3907EA21A29BB900A215CD /* QFTimerUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QFTimerUtil.h; sourceTree = ""; }; 70 | FDE2216E21A7982E0050521D /* QFTimerDataSourceModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = QFTimerDataSourceModel.h; sourceTree = ""; }; 71 | FDE2216F21A7982E0050521D /* QFTimerDataSourceModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = QFTimerDataSourceModel.m; sourceTree = ""; }; 72 | FDE2217121A79BD00050521D /* QFDateModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QFDateModel.m; sourceTree = ""; }; 73 | FDE2217221A79BD00050521D /* QFMinuteModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QFMinuteModel.m; sourceTree = ""; }; 74 | FDE2217321A79BD00050521D /* QFHourModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QFHourModel.h; sourceTree = ""; }; 75 | FDE2217421A79BD00050521D /* QFDateModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QFDateModel.h; sourceTree = ""; }; 76 | FDE2217521A79BD00050521D /* QFMinuteModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QFMinuteModel.h; sourceTree = ""; }; 77 | FDE2217621A79BD00050521D /* QFHourModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QFHourModel.m; sourceTree = ""; }; 78 | /* End PBXFileReference section */ 79 | 80 | /* Begin PBXFrameworksBuildPhase section */ 81 | BB3951451E288B8E000EBDD6 /* Frameworks */ = { 82 | isa = PBXFrameworksBuildPhase; 83 | buildActionMask = 2147483647; 84 | files = ( 85 | ); 86 | runOnlyForDeploymentPostprocessing = 0; 87 | }; 88 | BB39515E1E288B8F000EBDD6 /* Frameworks */ = { 89 | isa = PBXFrameworksBuildPhase; 90 | buildActionMask = 2147483647; 91 | files = ( 92 | ); 93 | runOnlyForDeploymentPostprocessing = 0; 94 | }; 95 | BB3951691E288B8F000EBDD6 /* Frameworks */ = { 96 | isa = PBXFrameworksBuildPhase; 97 | buildActionMask = 2147483647; 98 | files = ( 99 | ); 100 | runOnlyForDeploymentPostprocessing = 0; 101 | }; 102 | /* End PBXFrameworksBuildPhase section */ 103 | 104 | /* Begin PBXGroup section */ 105 | 851DDD7B1FBA9334007C1E1F /* QFTimePickerView */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | 851DDD7C1FBA935F007C1E1F /* QFTimePickerView.h */, 109 | 851DDD7D1FBA935F007C1E1F /* QFTimePickerView.m */, 110 | ); 111 | path = QFTimePickerView; 112 | sourceTree = ""; 113 | }; 114 | BB39513F1E288B8E000EBDD6 = { 115 | isa = PBXGroup; 116 | children = ( 117 | BB39514A1E288B8E000EBDD6 /* QFDatePickerView */, 118 | BB3951641E288B8F000EBDD6 /* QFDatePickerViewTests */, 119 | BB39516F1E288B8F000EBDD6 /* QFDatePickerViewUITests */, 120 | BB3951491E288B8E000EBDD6 /* Products */, 121 | ); 122 | sourceTree = ""; 123 | }; 124 | BB3951491E288B8E000EBDD6 /* Products */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | BB3951481E288B8E000EBDD6 /* QFDatePickerView.app */, 128 | BB3951611E288B8F000EBDD6 /* QFDatePickerViewTests.xctest */, 129 | BB39516C1E288B8F000EBDD6 /* QFDatePickerViewUITests.xctest */, 130 | ); 131 | name = Products; 132 | sourceTree = ""; 133 | }; 134 | BB39514A1E288B8E000EBDD6 /* QFDatePickerView */ = { 135 | isa = PBXGroup; 136 | children = ( 137 | FD3907E421A29BB900A215CD /* QFTimerPicker */, 138 | 851DDD7B1FBA9334007C1E1F /* QFTimePickerView */, 139 | BB3951831E288BDA000EBDD6 /* QFDatePickerView */, 140 | BB39514E1E288B8E000EBDD6 /* AppDelegate.h */, 141 | BB39514F1E288B8E000EBDD6 /* AppDelegate.m */, 142 | BB3951801E288BAB000EBDD6 /* ViewController.h */, 143 | BB3951811E288BAB000EBDD6 /* ViewController.m */, 144 | BB39517E1E288B9C000EBDD6 /* Main.storyboard */, 145 | BB3951571E288B8E000EBDD6 /* Assets.xcassets */, 146 | BB3951591E288B8E000EBDD6 /* LaunchScreen.storyboard */, 147 | BB39515C1E288B8E000EBDD6 /* Info.plist */, 148 | BB39514B1E288B8E000EBDD6 /* Supporting Files */, 149 | ); 150 | path = QFDatePickerView; 151 | sourceTree = ""; 152 | }; 153 | BB39514B1E288B8E000EBDD6 /* Supporting Files */ = { 154 | isa = PBXGroup; 155 | children = ( 156 | BB39514C1E288B8E000EBDD6 /* main.m */, 157 | ); 158 | name = "Supporting Files"; 159 | sourceTree = ""; 160 | }; 161 | BB3951641E288B8F000EBDD6 /* QFDatePickerViewTests */ = { 162 | isa = PBXGroup; 163 | children = ( 164 | BB3951651E288B8F000EBDD6 /* QFDatePickerViewTests.m */, 165 | BB3951671E288B8F000EBDD6 /* Info.plist */, 166 | ); 167 | path = QFDatePickerViewTests; 168 | sourceTree = ""; 169 | }; 170 | BB39516F1E288B8F000EBDD6 /* QFDatePickerViewUITests */ = { 171 | isa = PBXGroup; 172 | children = ( 173 | BB3951701E288B8F000EBDD6 /* QFDatePickerViewUITests.m */, 174 | BB3951721E288B8F000EBDD6 /* Info.plist */, 175 | ); 176 | path = QFDatePickerViewUITests; 177 | sourceTree = ""; 178 | }; 179 | BB3951831E288BDA000EBDD6 /* QFDatePickerView */ = { 180 | isa = PBXGroup; 181 | children = ( 182 | BB3951841E288BDA000EBDD6 /* QFDatePickerView.h */, 183 | BB3951851E288BDA000EBDD6 /* QFDatePickerView.m */, 184 | ); 185 | path = QFDatePickerView; 186 | sourceTree = ""; 187 | }; 188 | FD3907E421A29BB900A215CD /* QFTimerPicker */ = { 189 | isa = PBXGroup; 190 | children = ( 191 | FD3907E521A29BB900A215CD /* QFTimerPicker */, 192 | FD3907E821A29BB900A215CD /* Uitils */, 193 | FD3907EB21A29BB900A215CD /* Model */, 194 | ); 195 | path = QFTimerPicker; 196 | sourceTree = ""; 197 | }; 198 | FD3907E521A29BB900A215CD /* QFTimerPicker */ = { 199 | isa = PBXGroup; 200 | children = ( 201 | FD3907E621A29BB900A215CD /* QFTimerPicker.h */, 202 | FD3907E721A29BB900A215CD /* QFTimerPicker.m */, 203 | ); 204 | path = QFTimerPicker; 205 | sourceTree = ""; 206 | }; 207 | FD3907E821A29BB900A215CD /* Uitils */ = { 208 | isa = PBXGroup; 209 | children = ( 210 | FD3907EA21A29BB900A215CD /* QFTimerUtil.h */, 211 | FD3907E921A29BB900A215CD /* QFTimerUtil.m */, 212 | ); 213 | path = Uitils; 214 | sourceTree = ""; 215 | }; 216 | FD3907EB21A29BB900A215CD /* Model */ = { 217 | isa = PBXGroup; 218 | children = ( 219 | FDE2217421A79BD00050521D /* QFDateModel.h */, 220 | FDE2217121A79BD00050521D /* QFDateModel.m */, 221 | FDE2217321A79BD00050521D /* QFHourModel.h */, 222 | FDE2217621A79BD00050521D /* QFHourModel.m */, 223 | FDE2217521A79BD00050521D /* QFMinuteModel.h */, 224 | FDE2217221A79BD00050521D /* QFMinuteModel.m */, 225 | FDE2216E21A7982E0050521D /* QFTimerDataSourceModel.h */, 226 | FDE2216F21A7982E0050521D /* QFTimerDataSourceModel.m */, 227 | ); 228 | path = Model; 229 | sourceTree = ""; 230 | }; 231 | /* End PBXGroup section */ 232 | 233 | /* Begin PBXNativeTarget section */ 234 | BB3951471E288B8E000EBDD6 /* QFDatePickerView */ = { 235 | isa = PBXNativeTarget; 236 | buildConfigurationList = BB3951751E288B8F000EBDD6 /* Build configuration list for PBXNativeTarget "QFDatePickerView" */; 237 | buildPhases = ( 238 | BB3951441E288B8E000EBDD6 /* Sources */, 239 | BB3951451E288B8E000EBDD6 /* Frameworks */, 240 | BB3951461E288B8E000EBDD6 /* Resources */, 241 | ); 242 | buildRules = ( 243 | ); 244 | dependencies = ( 245 | ); 246 | name = QFDatePickerView; 247 | productName = QFDatePickerView; 248 | productReference = BB3951481E288B8E000EBDD6 /* QFDatePickerView.app */; 249 | productType = "com.apple.product-type.application"; 250 | }; 251 | BB3951601E288B8F000EBDD6 /* QFDatePickerViewTests */ = { 252 | isa = PBXNativeTarget; 253 | buildConfigurationList = BB3951781E288B8F000EBDD6 /* Build configuration list for PBXNativeTarget "QFDatePickerViewTests" */; 254 | buildPhases = ( 255 | BB39515D1E288B8F000EBDD6 /* Sources */, 256 | BB39515E1E288B8F000EBDD6 /* Frameworks */, 257 | BB39515F1E288B8F000EBDD6 /* Resources */, 258 | ); 259 | buildRules = ( 260 | ); 261 | dependencies = ( 262 | BB3951631E288B8F000EBDD6 /* PBXTargetDependency */, 263 | ); 264 | name = QFDatePickerViewTests; 265 | productName = QFDatePickerViewTests; 266 | productReference = BB3951611E288B8F000EBDD6 /* QFDatePickerViewTests.xctest */; 267 | productType = "com.apple.product-type.bundle.unit-test"; 268 | }; 269 | BB39516B1E288B8F000EBDD6 /* QFDatePickerViewUITests */ = { 270 | isa = PBXNativeTarget; 271 | buildConfigurationList = BB39517B1E288B8F000EBDD6 /* Build configuration list for PBXNativeTarget "QFDatePickerViewUITests" */; 272 | buildPhases = ( 273 | BB3951681E288B8F000EBDD6 /* Sources */, 274 | BB3951691E288B8F000EBDD6 /* Frameworks */, 275 | BB39516A1E288B8F000EBDD6 /* Resources */, 276 | ); 277 | buildRules = ( 278 | ); 279 | dependencies = ( 280 | BB39516E1E288B8F000EBDD6 /* PBXTargetDependency */, 281 | ); 282 | name = QFDatePickerViewUITests; 283 | productName = QFDatePickerViewUITests; 284 | productReference = BB39516C1E288B8F000EBDD6 /* QFDatePickerViewUITests.xctest */; 285 | productType = "com.apple.product-type.bundle.ui-testing"; 286 | }; 287 | /* End PBXNativeTarget section */ 288 | 289 | /* Begin PBXProject section */ 290 | BB3951401E288B8E000EBDD6 /* Project object */ = { 291 | isa = PBXProject; 292 | attributes = { 293 | LastUpgradeCheck = 0820; 294 | ORGANIZATIONNAME = "情风"; 295 | TargetAttributes = { 296 | BB3951471E288B8E000EBDD6 = { 297 | CreatedOnToolsVersion = 8.2; 298 | ProvisioningStyle = Automatic; 299 | }; 300 | BB3951601E288B8F000EBDD6 = { 301 | CreatedOnToolsVersion = 8.2; 302 | ProvisioningStyle = Automatic; 303 | TestTargetID = BB3951471E288B8E000EBDD6; 304 | }; 305 | BB39516B1E288B8F000EBDD6 = { 306 | CreatedOnToolsVersion = 8.2; 307 | ProvisioningStyle = Automatic; 308 | TestTargetID = BB3951471E288B8E000EBDD6; 309 | }; 310 | }; 311 | }; 312 | buildConfigurationList = BB3951431E288B8E000EBDD6 /* Build configuration list for PBXProject "QFDatePickerView" */; 313 | compatibilityVersion = "Xcode 3.2"; 314 | developmentRegion = English; 315 | hasScannedForEncodings = 0; 316 | knownRegions = ( 317 | en, 318 | Base, 319 | ); 320 | mainGroup = BB39513F1E288B8E000EBDD6; 321 | productRefGroup = BB3951491E288B8E000EBDD6 /* Products */; 322 | projectDirPath = ""; 323 | projectRoot = ""; 324 | targets = ( 325 | BB3951471E288B8E000EBDD6 /* QFDatePickerView */, 326 | BB3951601E288B8F000EBDD6 /* QFDatePickerViewTests */, 327 | BB39516B1E288B8F000EBDD6 /* QFDatePickerViewUITests */, 328 | ); 329 | }; 330 | /* End PBXProject section */ 331 | 332 | /* Begin PBXResourcesBuildPhase section */ 333 | BB3951461E288B8E000EBDD6 /* Resources */ = { 334 | isa = PBXResourcesBuildPhase; 335 | buildActionMask = 2147483647; 336 | files = ( 337 | BB39517F1E288B9C000EBDD6 /* Main.storyboard in Resources */, 338 | BB39515B1E288B8E000EBDD6 /* LaunchScreen.storyboard in Resources */, 339 | BB3951581E288B8E000EBDD6 /* Assets.xcassets in Resources */, 340 | ); 341 | runOnlyForDeploymentPostprocessing = 0; 342 | }; 343 | BB39515F1E288B8F000EBDD6 /* Resources */ = { 344 | isa = PBXResourcesBuildPhase; 345 | buildActionMask = 2147483647; 346 | files = ( 347 | ); 348 | runOnlyForDeploymentPostprocessing = 0; 349 | }; 350 | BB39516A1E288B8F000EBDD6 /* Resources */ = { 351 | isa = PBXResourcesBuildPhase; 352 | buildActionMask = 2147483647; 353 | files = ( 354 | ); 355 | runOnlyForDeploymentPostprocessing = 0; 356 | }; 357 | /* End PBXResourcesBuildPhase section */ 358 | 359 | /* Begin PBXSourcesBuildPhase section */ 360 | BB3951441E288B8E000EBDD6 /* Sources */ = { 361 | isa = PBXSourcesBuildPhase; 362 | buildActionMask = 2147483647; 363 | files = ( 364 | 851DDD7E1FBA935F007C1E1F /* QFTimePickerView.m in Sources */, 365 | FDE2217721A79BD00050521D /* QFDateModel.m in Sources */, 366 | BB3951821E288BAB000EBDD6 /* ViewController.m in Sources */, 367 | FD3907F221A29BB900A215CD /* QFTimerPicker.m in Sources */, 368 | BB3951501E288B8E000EBDD6 /* AppDelegate.m in Sources */, 369 | FDE2217021A7982E0050521D /* QFTimerDataSourceModel.m in Sources */, 370 | FDE2217821A79BD00050521D /* QFMinuteModel.m in Sources */, 371 | FDE2217921A79BD00050521D /* QFHourModel.m in Sources */, 372 | FD3907F321A29BB900A215CD /* QFTimerUtil.m in Sources */, 373 | BB39514D1E288B8E000EBDD6 /* main.m in Sources */, 374 | BB3951861E288BDA000EBDD6 /* QFDatePickerView.m in Sources */, 375 | ); 376 | runOnlyForDeploymentPostprocessing = 0; 377 | }; 378 | BB39515D1E288B8F000EBDD6 /* Sources */ = { 379 | isa = PBXSourcesBuildPhase; 380 | buildActionMask = 2147483647; 381 | files = ( 382 | BB3951661E288B8F000EBDD6 /* QFDatePickerViewTests.m in Sources */, 383 | ); 384 | runOnlyForDeploymentPostprocessing = 0; 385 | }; 386 | BB3951681E288B8F000EBDD6 /* Sources */ = { 387 | isa = PBXSourcesBuildPhase; 388 | buildActionMask = 2147483647; 389 | files = ( 390 | BB3951711E288B8F000EBDD6 /* QFDatePickerViewUITests.m in Sources */, 391 | ); 392 | runOnlyForDeploymentPostprocessing = 0; 393 | }; 394 | /* End PBXSourcesBuildPhase section */ 395 | 396 | /* Begin PBXTargetDependency section */ 397 | BB3951631E288B8F000EBDD6 /* PBXTargetDependency */ = { 398 | isa = PBXTargetDependency; 399 | target = BB3951471E288B8E000EBDD6 /* QFDatePickerView */; 400 | targetProxy = BB3951621E288B8F000EBDD6 /* PBXContainerItemProxy */; 401 | }; 402 | BB39516E1E288B8F000EBDD6 /* PBXTargetDependency */ = { 403 | isa = PBXTargetDependency; 404 | target = BB3951471E288B8E000EBDD6 /* QFDatePickerView */; 405 | targetProxy = BB39516D1E288B8F000EBDD6 /* PBXContainerItemProxy */; 406 | }; 407 | /* End PBXTargetDependency section */ 408 | 409 | /* Begin PBXVariantGroup section */ 410 | BB3951591E288B8E000EBDD6 /* LaunchScreen.storyboard */ = { 411 | isa = PBXVariantGroup; 412 | children = ( 413 | BB39515A1E288B8E000EBDD6 /* Base */, 414 | ); 415 | name = LaunchScreen.storyboard; 416 | sourceTree = ""; 417 | }; 418 | /* End PBXVariantGroup section */ 419 | 420 | /* Begin XCBuildConfiguration section */ 421 | BB3951731E288B8F000EBDD6 /* Debug */ = { 422 | isa = XCBuildConfiguration; 423 | buildSettings = { 424 | ALWAYS_SEARCH_USER_PATHS = NO; 425 | CLANG_ANALYZER_NONNULL = YES; 426 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 427 | CLANG_CXX_LIBRARY = "libc++"; 428 | CLANG_ENABLE_MODULES = YES; 429 | CLANG_ENABLE_OBJC_ARC = YES; 430 | CLANG_WARN_BOOL_CONVERSION = YES; 431 | CLANG_WARN_CONSTANT_CONVERSION = YES; 432 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 433 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 434 | CLANG_WARN_EMPTY_BODY = YES; 435 | CLANG_WARN_ENUM_CONVERSION = YES; 436 | CLANG_WARN_INFINITE_RECURSION = YES; 437 | CLANG_WARN_INT_CONVERSION = YES; 438 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 439 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 440 | CLANG_WARN_UNREACHABLE_CODE = YES; 441 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 442 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 443 | COPY_PHASE_STRIP = NO; 444 | DEBUG_INFORMATION_FORMAT = dwarf; 445 | ENABLE_STRICT_OBJC_MSGSEND = YES; 446 | ENABLE_TESTABILITY = YES; 447 | GCC_C_LANGUAGE_STANDARD = gnu99; 448 | GCC_DYNAMIC_NO_PIC = NO; 449 | GCC_NO_COMMON_BLOCKS = YES; 450 | GCC_OPTIMIZATION_LEVEL = 0; 451 | GCC_PREPROCESSOR_DEFINITIONS = ( 452 | "DEBUG=1", 453 | "$(inherited)", 454 | ); 455 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 456 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 457 | GCC_WARN_UNDECLARED_SELECTOR = YES; 458 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 459 | GCC_WARN_UNUSED_FUNCTION = YES; 460 | GCC_WARN_UNUSED_VARIABLE = YES; 461 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 462 | MTL_ENABLE_DEBUG_INFO = YES; 463 | ONLY_ACTIVE_ARCH = YES; 464 | SDKROOT = iphoneos; 465 | }; 466 | name = Debug; 467 | }; 468 | BB3951741E288B8F000EBDD6 /* Release */ = { 469 | isa = XCBuildConfiguration; 470 | buildSettings = { 471 | ALWAYS_SEARCH_USER_PATHS = NO; 472 | CLANG_ANALYZER_NONNULL = YES; 473 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 474 | CLANG_CXX_LIBRARY = "libc++"; 475 | CLANG_ENABLE_MODULES = YES; 476 | CLANG_ENABLE_OBJC_ARC = YES; 477 | CLANG_WARN_BOOL_CONVERSION = YES; 478 | CLANG_WARN_CONSTANT_CONVERSION = YES; 479 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 480 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 481 | CLANG_WARN_EMPTY_BODY = YES; 482 | CLANG_WARN_ENUM_CONVERSION = YES; 483 | CLANG_WARN_INFINITE_RECURSION = YES; 484 | CLANG_WARN_INT_CONVERSION = YES; 485 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 486 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 487 | CLANG_WARN_UNREACHABLE_CODE = YES; 488 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 489 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 490 | COPY_PHASE_STRIP = NO; 491 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 492 | ENABLE_NS_ASSERTIONS = NO; 493 | ENABLE_STRICT_OBJC_MSGSEND = YES; 494 | GCC_C_LANGUAGE_STANDARD = gnu99; 495 | GCC_NO_COMMON_BLOCKS = YES; 496 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 497 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 498 | GCC_WARN_UNDECLARED_SELECTOR = YES; 499 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 500 | GCC_WARN_UNUSED_FUNCTION = YES; 501 | GCC_WARN_UNUSED_VARIABLE = YES; 502 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 503 | MTL_ENABLE_DEBUG_INFO = NO; 504 | SDKROOT = iphoneos; 505 | VALIDATE_PRODUCT = YES; 506 | }; 507 | name = Release; 508 | }; 509 | BB3951761E288B8F000EBDD6 /* Debug */ = { 510 | isa = XCBuildConfiguration; 511 | buildSettings = { 512 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 513 | INFOPLIST_FILE = QFDatePickerView/Info.plist; 514 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 515 | PRODUCT_BUNDLE_IDENTIFIER = JXT.QFDatePickerView; 516 | PRODUCT_NAME = "$(TARGET_NAME)"; 517 | }; 518 | name = Debug; 519 | }; 520 | BB3951771E288B8F000EBDD6 /* Release */ = { 521 | isa = XCBuildConfiguration; 522 | buildSettings = { 523 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 524 | INFOPLIST_FILE = QFDatePickerView/Info.plist; 525 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 526 | PRODUCT_BUNDLE_IDENTIFIER = JXT.QFDatePickerView; 527 | PRODUCT_NAME = "$(TARGET_NAME)"; 528 | }; 529 | name = Release; 530 | }; 531 | BB3951791E288B8F000EBDD6 /* Debug */ = { 532 | isa = XCBuildConfiguration; 533 | buildSettings = { 534 | BUNDLE_LOADER = "$(TEST_HOST)"; 535 | INFOPLIST_FILE = QFDatePickerViewTests/Info.plist; 536 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 537 | PRODUCT_BUNDLE_IDENTIFIER = JXT.QFDatePickerViewTests; 538 | PRODUCT_NAME = "$(TARGET_NAME)"; 539 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/QFDatePickerView.app/QFDatePickerView"; 540 | }; 541 | name = Debug; 542 | }; 543 | BB39517A1E288B8F000EBDD6 /* Release */ = { 544 | isa = XCBuildConfiguration; 545 | buildSettings = { 546 | BUNDLE_LOADER = "$(TEST_HOST)"; 547 | INFOPLIST_FILE = QFDatePickerViewTests/Info.plist; 548 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 549 | PRODUCT_BUNDLE_IDENTIFIER = JXT.QFDatePickerViewTests; 550 | PRODUCT_NAME = "$(TARGET_NAME)"; 551 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/QFDatePickerView.app/QFDatePickerView"; 552 | }; 553 | name = Release; 554 | }; 555 | BB39517C1E288B8F000EBDD6 /* Debug */ = { 556 | isa = XCBuildConfiguration; 557 | buildSettings = { 558 | INFOPLIST_FILE = QFDatePickerViewUITests/Info.plist; 559 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 560 | PRODUCT_BUNDLE_IDENTIFIER = JXT.QFDatePickerViewUITests; 561 | PRODUCT_NAME = "$(TARGET_NAME)"; 562 | TEST_TARGET_NAME = QFDatePickerView; 563 | }; 564 | name = Debug; 565 | }; 566 | BB39517D1E288B8F000EBDD6 /* Release */ = { 567 | isa = XCBuildConfiguration; 568 | buildSettings = { 569 | INFOPLIST_FILE = QFDatePickerViewUITests/Info.plist; 570 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 571 | PRODUCT_BUNDLE_IDENTIFIER = JXT.QFDatePickerViewUITests; 572 | PRODUCT_NAME = "$(TARGET_NAME)"; 573 | TEST_TARGET_NAME = QFDatePickerView; 574 | }; 575 | name = Release; 576 | }; 577 | /* End XCBuildConfiguration section */ 578 | 579 | /* Begin XCConfigurationList section */ 580 | BB3951431E288B8E000EBDD6 /* Build configuration list for PBXProject "QFDatePickerView" */ = { 581 | isa = XCConfigurationList; 582 | buildConfigurations = ( 583 | BB3951731E288B8F000EBDD6 /* Debug */, 584 | BB3951741E288B8F000EBDD6 /* Release */, 585 | ); 586 | defaultConfigurationIsVisible = 0; 587 | defaultConfigurationName = Release; 588 | }; 589 | BB3951751E288B8F000EBDD6 /* Build configuration list for PBXNativeTarget "QFDatePickerView" */ = { 590 | isa = XCConfigurationList; 591 | buildConfigurations = ( 592 | BB3951761E288B8F000EBDD6 /* Debug */, 593 | BB3951771E288B8F000EBDD6 /* Release */, 594 | ); 595 | defaultConfigurationIsVisible = 0; 596 | defaultConfigurationName = Release; 597 | }; 598 | BB3951781E288B8F000EBDD6 /* Build configuration list for PBXNativeTarget "QFDatePickerViewTests" */ = { 599 | isa = XCConfigurationList; 600 | buildConfigurations = ( 601 | BB3951791E288B8F000EBDD6 /* Debug */, 602 | BB39517A1E288B8F000EBDD6 /* Release */, 603 | ); 604 | defaultConfigurationIsVisible = 0; 605 | defaultConfigurationName = Release; 606 | }; 607 | BB39517B1E288B8F000EBDD6 /* Build configuration list for PBXNativeTarget "QFDatePickerViewUITests" */ = { 608 | isa = XCConfigurationList; 609 | buildConfigurations = ( 610 | BB39517C1E288B8F000EBDD6 /* Debug */, 611 | BB39517D1E288B8F000EBDD6 /* Release */, 612 | ); 613 | defaultConfigurationIsVisible = 0; 614 | defaultConfigurationName = Release; 615 | }; 616 | /* End XCConfigurationList section */ 617 | }; 618 | rootObject = BB3951401E288B8E000EBDD6 /* Project object */; 619 | } 620 | -------------------------------------------------------------------------------- /QFDatePickerView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /QFDatePickerView.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /QFDatePickerView.xcodeproj/project.xcworkspace/xcuserdata/iosyf-02.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qingfengiOS/QFDatePickerView/bb9192534c8929d5c79ed2cd3c3cf09b0d3086ce/QFDatePickerView.xcodeproj/project.xcworkspace/xcuserdata/iosyf-02.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /QFDatePickerView.xcodeproj/project.xcworkspace/xcuserdata/liyiping.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qingfengiOS/QFDatePickerView/bb9192534c8929d5c79ed2cd3c3cf09b0d3086ce/QFDatePickerView.xcodeproj/project.xcworkspace/xcuserdata/liyiping.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /QFDatePickerView.xcodeproj/xcuserdata/iosyf-02.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /QFDatePickerView.xcodeproj/xcuserdata/iosyf-02.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | QFDatePickerView.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /QFDatePickerView.xcodeproj/xcuserdata/jianxuntong.xcuserdatad/xcschemes/QFDatePickerView.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /QFDatePickerView.xcodeproj/xcuserdata/jianxuntong.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | QFDatePickerView.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | BB3951471E288B8E000EBDD6 16 | 17 | primary 18 | 19 | 20 | BB3951601E288B8F000EBDD6 21 | 22 | primary 23 | 24 | 25 | BB39516B1E288B8F000EBDD6 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /QFDatePickerView.xcodeproj/xcuserdata/liyiping.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /QFDatePickerView.xcodeproj/xcuserdata/liyiping.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | QFDatePickerView.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /QFDatePickerView/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // QFDatePickerView 4 | // 5 | // Created by 建讯通 on 2017/1/13. 6 | // Copyright © 2017年 情风. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /QFDatePickerView/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // QFDatePickerView 4 | // 5 | // Created by 建讯通 on 2017/1/13. 6 | // Copyright © 2017年 情风. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /QFDatePickerView/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 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /QFDatePickerView/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 | -------------------------------------------------------------------------------- /QFDatePickerView/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /QFDatePickerView/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 | 35 | 42 | 53 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /QFDatePickerView/QFDatePickerView/QFDatePickerView.h: -------------------------------------------------------------------------------- 1 | // 2 | // QFDatePickerView.h 3 | // dateDemo 4 | // 5 | // Created by 情风 on 2017/1/12. 6 | // Copyright © 2017年 情风. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface QFDatePickerView : UIView 12 | 13 | 14 | /** 15 | 初始化方法,只带年月的日期选择 16 | 17 | @param block 返回选中的日期 18 | @return QFDatePickerView对象 19 | */ 20 | - (instancetype)initDatePackerWithResponse:(void(^)(NSString*))block; 21 | 22 | 23 | /** 24 | 初始化方法,只带年月的日期选择 25 | 26 | @param superView picker的载体View 27 | @param block 返回选中的日期 28 | @return QFDatePickerView对象 29 | */ 30 | - (instancetype)initDatePackerWithSUperView:(UIView *)superView response:(void(^)(NSString*))block; 31 | 32 | 33 | /** 34 | 初始化方法,只带年份的日期选择 35 | 36 | @param block 返回选中的年份 37 | @return QFDatePickerView对象 38 | */ 39 | - (instancetype)initYearPickerViewWithResponse:(void(^)(NSString*))block; 40 | 41 | /** 42 | 初始化方法,只带年份的日期选择 43 | 44 | @param block 返回选中的年份 45 | @return QFDatePickerView对象 46 | */ 47 | - (instancetype)initYearPickerWithView:(UIView *)superView response:(void(^)(NSString*))block; 48 | 49 | /** 50 | 显示方法 51 | */ 52 | - (void)show; 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /QFDatePickerView/QFDatePickerView/QFDatePickerView.m: -------------------------------------------------------------------------------- 1 | // 2 | // QFDatePickerView.m 3 | // dateDemo 4 | // 5 | // Created by 情风 on 2017/1/12. 6 | // Copyright © 2017年 情风. All rights reserved. 7 | // 8 | 9 | #import "QFDatePickerView.h" 10 | #import "AppDelegate.h" 11 | 12 | @interface QFDatePickerView () { 13 | UIView *contentView; 14 | void(^backBlock)(NSString *); 15 | 16 | NSMutableArray *yearArray; 17 | NSMutableArray *monthArray; 18 | NSInteger currentYear; 19 | NSInteger currentMonth; 20 | NSString *restr; 21 | 22 | NSString *selectedYear; 23 | NSString *selectecMonth; 24 | 25 | BOOL onlySelectYear; 26 | 27 | UIView *superView; 28 | } 29 | 30 | 31 | @end 32 | 33 | @implementation QFDatePickerView 34 | 35 | #pragma mark - initDatePickerView 36 | /** 37 | 初始化方法,只带年月的日期选择 38 | 39 | @param block 返回选中的日期 40 | @return QFDatePickerView对象 41 | */ 42 | - (instancetype)initDatePackerWithResponse:(void (^)(NSString *))block{ 43 | if (self = [super init]) { 44 | self.frame = [UIScreen mainScreen].bounds; 45 | } 46 | [self setViewInterface]; 47 | if (block) { 48 | backBlock = block; 49 | } 50 | onlySelectYear = NO; 51 | return self; 52 | } 53 | 54 | /** 55 | 初始化方法,只带年月的日期选择 56 | 57 | @param superView picker的载体View 58 | @param block 返回选中的日期 59 | @return QFDatePickerView对象 60 | */ 61 | - (instancetype)initDatePackerWithSUperView:(UIView *)superView response:(void(^)(NSString*))block { 62 | if (self = [super init]) { 63 | self.frame = [UIScreen mainScreen].bounds; 64 | } 65 | [self setViewInterface]; 66 | if (block) { 67 | backBlock = block; 68 | } 69 | superView = superView; 70 | onlySelectYear = NO; 71 | return self; 72 | } 73 | 74 | /** 75 | 初始化方法,只带年份的日期选择 76 | 77 | @param block 返回选中的年份 78 | @return QFDatePickerView对象 79 | */ 80 | - (instancetype)initYearPickerViewWithResponse:(void(^)(NSString*))block { 81 | if (self = [super init]) { 82 | self.frame = [UIScreen mainScreen].bounds; 83 | } 84 | [self setViewInterface]; 85 | if (block) { 86 | backBlock = block; 87 | } 88 | onlySelectYear = YES; 89 | return self; 90 | } 91 | 92 | /** 93 | 初始化方法,只带年份的日期选择 94 | 95 | @param block 返回选中的年份 96 | @return QFDatePickerView对象 97 | */ 98 | - (instancetype)initYearPickerWithView:(UIView *)superView response:(void(^)(NSString*))block { 99 | if (self = [super init]) { 100 | self.frame = [UIScreen mainScreen].bounds; 101 | } 102 | [self setViewInterface]; 103 | if (block) { 104 | backBlock = block; 105 | } 106 | superView = superView; 107 | onlySelectYear = YES; 108 | return self; 109 | } 110 | 111 | #pragma mark - Configuration 112 | - (void)setViewInterface { 113 | 114 | [self getCurrentDate]; 115 | 116 | [self setYearArray]; 117 | 118 | [self setMonthArray]; 119 | 120 | contentView = [[UIView alloc] initWithFrame:CGRectMake(0, self.frame.size.height, self.frame.size.width, 300)]; 121 | [self addSubview:contentView]; 122 | //设置背景颜色为黑色,并有0.4的透明度 123 | self.backgroundColor = [UIColor colorWithWhite:0 alpha:0.4]; 124 | //添加白色view 125 | UIView *whiteView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, 40)]; 126 | whiteView.backgroundColor = [UIColor whiteColor]; 127 | [contentView addSubview:whiteView]; 128 | //添加确定和取消按钮 129 | for (int i = 0; i < 2; i ++) { 130 | UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake((self.frame.size.width - 60) * i, 0, 60, 40)]; 131 | [button setTitle:i == 0 ? @"取消" : @"确定" forState:UIControlStateNormal]; 132 | if (i == 0) { 133 | [button setTitleColor:[UIColor colorWithRed:97.0 / 255.0 green:97.0 / 255.0 blue:97.0 / 255.0 alpha:1] forState:UIControlStateNormal]; 134 | } else { 135 | [button setTitleColor:[UIColor redColor] forState:UIControlStateNormal]; 136 | } 137 | [whiteView addSubview:button]; 138 | [button addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside]; 139 | button.tag = 10 + i; 140 | } 141 | 142 | UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 40, CGRectGetWidth(self.bounds), 260)]; 143 | pickerView.delegate = self; 144 | pickerView.dataSource = self; 145 | pickerView.backgroundColor = [UIColor colorWithRed:240.0/255 green:243.0/255 blue:250.0/255 alpha:1]; 146 | 147 | //设置pickerView默认选中当前时间 148 | [pickerView selectRow:[selectedYear integerValue] - 1970 inComponent:0 animated:YES]; 149 | if (!onlySelectYear) { 150 | [pickerView selectRow:[selectecMonth integerValue] - 1 inComponent:1 animated:YES]; 151 | } 152 | 153 | [contentView addSubview:pickerView]; 154 | } 155 | 156 | - (void)getCurrentDate { 157 | //获取当前时间 (时间格式支持自定义) 158 | NSDateFormatter *formatter = [[NSDateFormatter alloc]init]; 159 | [formatter setDateFormat:@"yyyy-MM"];//自定义时间格式 160 | NSString *currentDateStr = [formatter stringFromDate:[NSDate date]]; 161 | //拆分年月成数组 162 | NSArray *dateArray = [currentDateStr componentsSeparatedByString:@"-"]; 163 | if (dateArray.count == 2) {//年 月 164 | currentYear = [[dateArray firstObject]integerValue]; 165 | currentMonth = [dateArray[1] integerValue]; 166 | } 167 | selectedYear = [NSString stringWithFormat:@"%ld",(long)currentYear]; 168 | selectecMonth = [NSString stringWithFormat:@"%ld",(long)currentMonth]; 169 | } 170 | 171 | - (void)setYearArray { 172 | //初始化年数据源数组 173 | yearArray = [[NSMutableArray alloc]init]; 174 | for (NSInteger i = 1970; i <= currentYear ; i++) { 175 | NSString *yearStr = [NSString stringWithFormat:@"%ld年",(long)i]; 176 | [yearArray addObject:yearStr]; 177 | } 178 | [yearArray addObject:@"至今"]; 179 | } 180 | 181 | - (void)setMonthArray { 182 | //初始化月数据源数组 183 | monthArray = [[NSMutableArray alloc]init]; 184 | 185 | if ([[selectedYear substringWithRange:NSMakeRange(0, 4)] isEqualToString:[NSString stringWithFormat:@"%ld",(long)currentYear]]) { 186 | for (NSInteger i = 1 ; i <= currentMonth; i++) { 187 | NSString *monthStr = [NSString stringWithFormat:@"%ld月",(long)i]; 188 | [monthArray addObject:monthStr]; 189 | } 190 | } else { 191 | for (NSInteger i = 1 ; i <= 12; i++) { 192 | NSString *monthStr = [NSString stringWithFormat:@"%ld月",(long)i]; 193 | [monthArray addObject:monthStr]; 194 | } 195 | } 196 | } 197 | 198 | #pragma mark - Actions 199 | - (void)buttonTapped:(UIButton *)sender { 200 | if (sender.tag == 10) { 201 | [self dismiss]; 202 | } else { 203 | if (onlySelectYear) { 204 | restr = [selectedYear stringByReplacingOccurrencesOfString:@"年" withString:@""]; 205 | } else { 206 | if ([selectecMonth isEqualToString:@""]) {//至今的情况下 不需要中间- 207 | restr = [NSString stringWithFormat:@"%@%@",selectedYear,selectecMonth]; 208 | } else { 209 | restr = [NSString stringWithFormat:@"%@-%@",selectedYear,selectecMonth]; 210 | } 211 | 212 | restr = [restr stringByReplacingOccurrencesOfString:@"年" withString:@""]; 213 | restr = [restr stringByReplacingOccurrencesOfString:@"月" withString:@""]; 214 | } 215 | backBlock(restr); 216 | [self dismiss]; 217 | } 218 | } 219 | 220 | #pragma mark - pickerView出现 221 | - (void)show { 222 | if (superView) { 223 | [superView addSubview:self]; 224 | } else { 225 | [[UIApplication sharedApplication].keyWindow addSubview:self]; 226 | } 227 | [UIView animateWithDuration:0.4 animations:^{ 228 | contentView.center = CGPointMake(self.frame.size.width/2, contentView.center.y - contentView.frame.size.height); 229 | }]; 230 | } 231 | #pragma mark - pickerView消失 232 | - (void)dismiss{ 233 | 234 | [UIView animateWithDuration:0.4 animations:^{ 235 | contentView.center = CGPointMake(self.frame.size.width/2, contentView.center.y + contentView.frame.size.height); 236 | } completion:^(BOOL finished) { 237 | [self removeFromSuperview]; 238 | }]; 239 | } 240 | 241 | #pragma mark - UIPickerViewDataSource UIPickerViewDelegate 242 | - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { 243 | if (onlySelectYear) {//只选择年 244 | return 1; 245 | } else { 246 | return 2; 247 | } 248 | 249 | } 250 | 251 | - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { 252 | if (onlySelectYear) {//只选择年 253 | return yearArray.count; 254 | } else { 255 | if (component == 0) { 256 | return yearArray.count; 257 | } else { 258 | return monthArray.count; 259 | } 260 | } 261 | return 0; 262 | } 263 | 264 | - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { 265 | if (onlySelectYear) {//只选择年 266 | return yearArray[row]; 267 | } else { 268 | if (component == 0) { 269 | return yearArray[row]; 270 | } else { 271 | return monthArray[row]; 272 | } 273 | } 274 | return @""; 275 | } 276 | 277 | - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { 278 | if (onlySelectYear) {//只选择年 279 | selectedYear = yearArray[row]; 280 | } else { 281 | if (component == 0) { 282 | selectedYear = yearArray[row]; 283 | if ([selectedYear isEqualToString:@"至今"]) {//至今的情况下,月份清空 284 | [monthArray removeAllObjects]; 285 | selectecMonth = @""; 286 | } else {//非至今的情况下,显示月份 287 | [self setMonthArray]; 288 | selectecMonth = [NSString stringWithFormat:@"%ld",(long)currentMonth]; 289 | } 290 | [pickerView reloadComponent:1]; 291 | 292 | } else { 293 | selectecMonth = monthArray[row]; 294 | } 295 | } 296 | } 297 | 298 | @end 299 | -------------------------------------------------------------------------------- /QFDatePickerView/QFTimePickerView/QFTimePickerView.h: -------------------------------------------------------------------------------- 1 | // 2 | // QFTimePickerView.h 3 | // QFDatePickerView 4 | // 5 | // Created by iosyf-02 on 2017/11/14. 6 | // Copyright © 2017年 情风. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface QFTimePickerView : UIView 12 | 13 | /** 14 | 初始化方法 15 | 16 | @param startHour 其实时间点 时 17 | @param endHour 结束时间点 时 18 | @param period 间隔多少分中 19 | @param block 返回选中的时间 20 | @return QFTimePickerView实例 21 | */ 22 | - (instancetype)initDatePackerWithStartHour:(NSString *)startHour endHour:(NSString *)endHour period:(NSInteger)period response:(void (^)(NSString *))block; 23 | 24 | - (void)show; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /QFDatePickerView/QFTimePickerView/QFTimePickerView.m: -------------------------------------------------------------------------------- 1 | // 2 | // QFTimePickerView.m 3 | // QFDatePickerView 4 | // 5 | // Created by iosyf-02 on 2017/11/14. 6 | // Copyright © 2017年 情风. All rights reserved. 7 | // 8 | 9 | #import "QFTimePickerView.h" 10 | 11 | @interface QFTimePickerView () { 12 | UIView *contentView; 13 | void(^backBlock)(NSString *); 14 | 15 | NSMutableArray *hourArray; 16 | NSMutableArray *minArray; 17 | NSInteger currentHour; 18 | NSInteger currentMin; 19 | NSString *restr; 20 | 21 | NSString *selectedHour; 22 | NSString *selectedMin; 23 | } 24 | 25 | @property (nonatomic, assign) NSString *startTime; 26 | @property (nonatomic, assign) NSString *endTime; 27 | @property (nonatomic, assign) NSInteger period; 28 | 29 | @end 30 | 31 | @implementation QFTimePickerView 32 | 33 | /** 34 | 初始化方法 35 | 36 | @param startHour 其实时间点 时 37 | @param endHour 结束时间点 时 38 | @param period 间隔多少分中 39 | @param block 返回选中的时间 40 | @return QFTimePickerView实例 41 | */ 42 | - (instancetype)initDatePackerWithStartHour:(NSString *)startHour endHour:(NSString *)endHour period:(NSInteger)period response:(void (^)(NSString *))block{ 43 | if (self = [super init]) { 44 | self.frame = [UIScreen mainScreen].bounds; 45 | } 46 | _startTime = startHour; 47 | _endTime = endHour; 48 | _period = period; 49 | 50 | [self initDataSource]; 51 | [self initAppreaence]; 52 | 53 | if (block) { 54 | backBlock = block; 55 | } 56 | return self; 57 | } 58 | 59 | #pragma mark - initDataSource 60 | - (void)initDataSource { 61 | 62 | [self configHourArray]; 63 | [self configMinArray]; 64 | 65 | selectedHour = hourArray[0]; 66 | selectedMin = minArray[0]; 67 | } 68 | 69 | - (void)configHourArray {//配置小时数据源数组 70 | //初始化小时数据源数组 71 | hourArray = [[NSMutableArray alloc]init]; 72 | 73 | NSString *startHour = [_startTime substringWithRange:NSMakeRange(0, 2)]; 74 | NSString *endHour = [_endTime substringWithRange:NSMakeRange(0, 2)]; 75 | 76 | if ([startHour integerValue] > [endHour integerValue]) {//跨天 77 | NSString *minStr = @""; 78 | for (NSInteger i = [startHour integerValue]; i < 24; i++) {//加当天的小时数 79 | if (i < 10) { 80 | minStr = [NSString stringWithFormat:@"0%ld",i]; 81 | } else { 82 | minStr = [NSString stringWithFormat:@"%ld",i]; 83 | } 84 | [hourArray addObject:minStr]; 85 | } 86 | for (NSInteger i = 0; i <= [endHour integerValue]; i++) {//加次天的小时数 87 | if (i < 10) { 88 | minStr = [NSString stringWithFormat:@"0%ld",i]; 89 | } else { 90 | minStr = [NSString stringWithFormat:@"%ld",i]; 91 | } 92 | [hourArray addObject:minStr]; 93 | } 94 | 95 | } else { 96 | for (NSInteger i = [startHour integerValue]; i < [endHour integerValue]; i++) {//加小时数 97 | NSString *minStr = @""; 98 | if (i < 10) { 99 | minStr = [NSString stringWithFormat:@"0%ld",i]; 100 | } else { 101 | minStr = [NSString stringWithFormat:@"%ld",i]; 102 | } 103 | [hourArray addObject:minStr]; 104 | } 105 | } 106 | 107 | } 108 | 109 | - (void)configMinArray {//配置分钟数据源数组 110 | minArray = [[NSMutableArray alloc]init]; 111 | for (NSInteger i = 1 ; i <= 60; i++) { 112 | NSString *minStr = @""; 113 | if (i % _period == 0) { 114 | if (i < 10) { 115 | minStr = [NSString stringWithFormat:@"0%ld",(long)i]; 116 | } else { 117 | minStr = [NSString stringWithFormat:@"%ld",(long)i]; 118 | } 119 | [minArray addObject:minStr]; 120 | } 121 | } 122 | [minArray insertObject:@"00" atIndex:0]; 123 | [minArray removeLastObject]; 124 | } 125 | 126 | #pragma mark - initAppreaence 127 | - (void)initAppreaence { 128 | 129 | contentView = [[UIView alloc] initWithFrame:CGRectMake(0, self.frame.size.height, self.frame.size.width, 300)]; 130 | [self addSubview:contentView]; 131 | //设置背景颜色为黑色,并有0.4的透明度 132 | self.backgroundColor = [UIColor colorWithWhite:0 alpha:0.4]; 133 | //添加白色view 134 | UIView *whiteView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, 40)]; 135 | whiteView.backgroundColor = [UIColor whiteColor]; 136 | [contentView addSubview:whiteView]; 137 | //添加确定和取消按钮 138 | for (int i = 0; i < 2; i ++) { 139 | UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake((self.frame.size.width - 60) * i, 0, 60, 40)]; 140 | [button setTitle:i == 0 ? @"取消" : @"确定" forState:UIControlStateNormal]; 141 | if (i == 0) { 142 | [button setTitleColor:[UIColor colorWithRed:97.0 / 255.0 green:97.0 / 255.0 blue:97.0 / 255.0 alpha:1] forState:UIControlStateNormal]; 143 | } else { 144 | [button setTitleColor:[UIColor redColor] forState:UIControlStateNormal]; 145 | } 146 | [whiteView addSubview:button]; 147 | [button addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside]; 148 | button.tag = 10 + i; 149 | } 150 | 151 | UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 40, CGRectGetWidth(self.bounds), 260)]; 152 | pickerView.delegate = self; 153 | pickerView.dataSource = self; 154 | pickerView.backgroundColor = [UIColor colorWithRed:240.0/255 green:243.0/255 blue:250.0/255 alpha:1]; 155 | 156 | //设置pickerView默认第一行 这里也可默认选中其他行 修改selectRow即可 157 | [pickerView selectRow:0 inComponent:0 animated:YES]; 158 | [pickerView selectRow:0 inComponent:1 animated:YES]; 159 | 160 | [contentView addSubview:pickerView]; 161 | } 162 | 163 | #pragma mark - Actions 164 | - (void)buttonTapped:(UIButton *)sender { 165 | if (sender.tag == 10) { 166 | [self dismiss]; 167 | } else { 168 | 169 | restr = [NSString stringWithFormat:@"%@:%@",selectedHour,selectedMin]; 170 | 171 | backBlock(restr); 172 | [self dismiss]; 173 | } 174 | } 175 | 176 | #pragma mark - pickerView出现 177 | - (void)show { 178 | 179 | [[UIApplication sharedApplication].keyWindow addSubview:self]; 180 | 181 | [UIView animateWithDuration:0.4 animations:^{ 182 | contentView.center = CGPointMake(self.frame.size.width/2, contentView.center.y - contentView.frame.size.height); 183 | }]; 184 | } 185 | 186 | #pragma mark - pickerView消失 187 | - (void)dismiss{ 188 | 189 | [UIView animateWithDuration:0.4 animations:^{ 190 | contentView.center = CGPointMake(self.frame.size.width/2, contentView.center.y + contentView.frame.size.height); 191 | } completion:^(BOOL finished) { 192 | [self removeFromSuperview]; 193 | }]; 194 | } 195 | 196 | #pragma mark - UIPickerViewDataSource UIPickerViewDelegate 197 | - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { 198 | return 2; 199 | } 200 | 201 | - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { 202 | if (component == 0) { 203 | return hourArray.count; 204 | } 205 | else { 206 | return minArray.count; 207 | } 208 | } 209 | 210 | - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { 211 | if (component == 0) { 212 | return hourArray[row]; 213 | } else { 214 | return minArray[row]; 215 | } 216 | } 217 | 218 | - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { 219 | if (component == 0) { 220 | selectedHour = hourArray[row]; 221 | 222 | if ([selectedHour isEqualToString:[hourArray lastObject]]) { 223 | [pickerView selectRow:0 inComponent:1 animated:YES]; 224 | selectedMin = @"00"; 225 | } 226 | [pickerView reloadComponent:1]; 227 | 228 | } else { 229 | if ([selectedHour isEqualToString:[hourArray lastObject]]) { 230 | [pickerView selectRow:0 inComponent:1 animated:YES]; 231 | selectedMin = @"00"; 232 | } else { 233 | selectedMin = minArray[row]; 234 | } 235 | } 236 | } 237 | @end 238 | -------------------------------------------------------------------------------- /QFDatePickerView/QFTimerPicker/Model/QFDateModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // QFDateModel.h 3 | // QFTimerPicker 4 | // 5 | // Created by 情风 on 2018/11/19. 6 | // Copyright © 2018年 qingfengiOS. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface QFDateModel : NSObject 12 | 13 | /// 实际日期 14 | @property (nonatomic, copy) NSString *dateString; 15 | 16 | /// 展示的日期 17 | @property (nonatomic, copy) NSString *showDateString; 18 | 19 | @end 20 | 21 | -------------------------------------------------------------------------------- /QFDatePickerView/QFTimerPicker/Model/QFDateModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // QFDateModel.m 3 | // QFTimerPicker 4 | // 5 | // Created by 情风 on 2018/11/19. 6 | // Copyright © 2018年 qingfengiOS. All rights reserved. 7 | // 8 | 9 | #import "QFDateModel.h" 10 | 11 | @implementation QFDateModel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /QFDatePickerView/QFTimerPicker/Model/QFHourModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // QFHourModel.h 3 | // QFTimerPicker 4 | // 5 | // Created by 情风 on 2018/11/19. 6 | // Copyright © 2018年 qingfengiOS. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface QFHourModel : NSObject 12 | 13 | /// 实际小时 14 | @property (nonatomic, copy) NSString *hourString; 15 | 16 | /// 展示的小时 17 | @property (nonatomic, copy) NSString *showHourString; 18 | @end 19 | -------------------------------------------------------------------------------- /QFDatePickerView/QFTimerPicker/Model/QFHourModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // QFHourModel.m 3 | // QFTimerPicker 4 | // 5 | // Created by 情风 on 2018/11/19. 6 | // Copyright © 2018年 qingfengiOS. All rights reserved. 7 | // 8 | 9 | #import "QFHourModel.h" 10 | 11 | @implementation QFHourModel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /QFDatePickerView/QFTimerPicker/Model/QFMinuteModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // QFMinuteModel.h 3 | // QFTimerPicker 4 | // 5 | // Created by 情风 on 2018/11/19. 6 | // Copyright © 2018年 qingfengiOS. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface QFMinuteModel : NSObject 12 | 13 | /// 实际分钟 14 | @property (nonatomic, copy) NSString *minuteString; 15 | 16 | /// 展示的分钟 17 | @property (nonatomic, copy) NSString *showMinuteString; 18 | @end 19 | -------------------------------------------------------------------------------- /QFDatePickerView/QFTimerPicker/Model/QFMinuteModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // QFMinuteModel.m 3 | // QFTimerPicker 4 | // 5 | // Created by 情风 on 2018/11/19. 6 | // Copyright © 2018年 qingfengiOS. All rights reserved. 7 | // 8 | 9 | #import "QFMinuteModel.h" 10 | 11 | @implementation QFMinuteModel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /QFDatePickerView/QFTimerPicker/Model/QFTimerDataSourceModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // QFTimerDataSourceModel.h 3 | // QFDatePickerView 4 | // 5 | // Created by 情风 on 2018/11/23. 6 | // Copyright © 2018 情风. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #pragma mark - pickerView的数据源 12 | @interface QFTimerDataSourceModel : NSObject 13 | 14 | /// 日期数据源 15 | @property (nonatomic, strong) NSMutableArray *dateArray; 16 | 17 | /// 小时数据源 18 | @property (nonatomic, strong) NSMutableArray *hourArray; 19 | 20 | /// 当天的小时数据源 21 | @property (nonatomic, strong) NSMutableArray *todayHourArray; 22 | 23 | /// 分钟数据源 24 | @property (nonatomic, strong) NSMutableArray *minuteArray; 25 | 26 | /// 当天的分钟数据源 27 | @property (nonatomic, strong) NSMutableArray *todayMinuteArray; 28 | 29 | @end 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /QFDatePickerView/QFTimerPicker/Model/QFTimerDataSourceModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // QFTimerDataSourceModel.m 3 | // QFDatePickerView 4 | // 5 | // Created by 情风 on 2018/11/23. 6 | // Copyright © 2018 情风. All rights reserved. 7 | // 8 | 9 | #import "QFTimerDataSourceModel.h" 10 | 11 | @implementation QFTimerDataSourceModel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /QFDatePickerView/QFTimerPicker/QFTimerPicker/QFTimerPicker.h: -------------------------------------------------------------------------------- 1 | // 2 | // QFTimerPicker.h 3 | // QFTimerPicker 4 | // 5 | // Created by 情风 on 2018/11/19. 6 | // Copyright © 2018年 qingfengiOS. All rights reserved. 7 | // 8 | 9 | #import 10 | typedef void(^ReturnBlock)(NSString *selectedStr); 11 | 12 | @interface QFTimerPicker : UIView 13 | 14 | /** 15 | 初始化时间选择 16 | 17 | @param block 回调block 参数即是选择的日期 18 | @return 时间选择器实例 19 | */ 20 | - (instancetype)initWithResponse:(ReturnBlock)block; 21 | 22 | /** 23 | 初始化时间选择 24 | 25 | @param superView 时间选择器的父View,若为空,将时间选择器加载在window上面 26 | @param block 回调block 参数即是选择的日期 27 | @return 时间选择器实例 28 | */ 29 | - (instancetype)initWithSuperView:(UIView *)superView response:(ReturnBlock)block; 30 | 31 | 32 | /** 33 | pickerView 出现 34 | */ 35 | - (void)show ; 36 | 37 | /** 38 | pickerView 消失 39 | */ 40 | - (void)dismiss; 41 | @end 42 | -------------------------------------------------------------------------------- /QFDatePickerView/QFTimerPicker/QFTimerPicker/QFTimerPicker.m: -------------------------------------------------------------------------------- 1 | // 2 | // QFTimerPicker.m 3 | // QFTimerPicker 4 | // 5 | // Created by 情风 on 2018/11/19. 6 | // Copyright © 2018年 qingfengiOS. All rights reserved. 7 | // 8 | 9 | #import "QFTimerPicker.h" 10 | #import "QFTimerUtil.h" 11 | #import "QFTimerDataSourceModel.h" 12 | #import "QFDateModel.h" 13 | #import "QFHourModel.h" 14 | #import "QFMinuteModel.h" 15 | 16 | @interface QFTimerPicker () 17 | 18 | /// 底层View 19 | @property (nonatomic, strong) UIView *contentView; 20 | 21 | /// 该pickerView所加载在的View 如果为nil就加载在Window上 22 | @property (nonatomic, strong) UIView *superView; 23 | 24 | /// 回调Block 25 | @property (nonatomic, copy) ReturnBlock returnBlock; 26 | 27 | /// 选中的日期下标 28 | @property (nonatomic, assign) NSInteger selectedDateIndex; 29 | 30 | /// 选中的小时下标 31 | @property (nonatomic, assign) NSInteger selectedHourIndex; 32 | 33 | /// 选中的分钟下标 34 | @property (nonatomic, assign) NSInteger selectedMinuteIndex; 35 | 36 | @property (nonatomic, strong) QFTimerDataSourceModel *dataSourceModel; 37 | 38 | @end 39 | 40 | @implementation QFTimerPicker 41 | 42 | #pragma mark - Life Cycle 43 | - (instancetype)initWithResponse:(ReturnBlock)block { 44 | if (self = [super init]) { 45 | [self initDataSource]; 46 | [self initAppreaence]; 47 | 48 | } 49 | self.returnBlock = block; 50 | return self; 51 | } 52 | 53 | - (instancetype)initWithSuperView:(UIView *)superView response:(ReturnBlock)block { 54 | if (self = [super init]) { 55 | [self initDataSource]; 56 | [self initAppreaence]; 57 | } 58 | self.returnBlock = block; 59 | self.superView = superView; 60 | return self; 61 | } 62 | 63 | #pragma mark - InitDataSource 64 | - (void)initDataSource { 65 | self.selectedDateIndex = 0; 66 | self.selectedHourIndex = 0; 67 | self.selectedMinuteIndex = 0; 68 | 69 | self.dataSourceModel = [QFTimerUtil configDataSource]; 70 | } 71 | 72 | #pragma mark - InitAppreaence 73 | - (void)initAppreaence { 74 | 75 | self.frame = [UIScreen mainScreen].bounds; 76 | //设置背景颜色为黑色,并有0.4的透明度 77 | self.backgroundColor = [UIColor colorWithWhite:0 alpha:0.4]; 78 | 79 | self.contentView = [[UIView alloc] initWithFrame:CGRectMake(0, [UIScreen mainScreen].bounds.size.height - 260, [UIScreen mainScreen].bounds.size.width, 260)]; 80 | [self addSubview:self.contentView]; 81 | 82 | 83 | //添加白色view 84 | UIView *whiteView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 50)]; 85 | whiteView.backgroundColor = [UIColor whiteColor]; 86 | [self.contentView addSubview:whiteView]; 87 | 88 | //添加确定和取消按钮 89 | for (int i = 0; i < 2; i ++) { 90 | UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(([UIScreen mainScreen].bounds.size.width - 80) * i, 0, 80, 50)]; 91 | button.titleLabel.font = [UIFont systemFontOfSize:14.0f]; 92 | [button setTitle:i == 0 ? @"取消" : @"确认" forState:UIControlStateNormal]; 93 | 94 | if (i != 0) { 95 | [button setTitleColor:[UIColor colorWithRed:41.0 / 255.0 green:152.0 / 255.0 blue:255.0 / 255.0 alpha:1] forState:UIControlStateNormal]; 96 | } else { 97 | [button setTitleColor:[UIColor colorWithRed:102.0 / 255.0 green:102.0 / 255.0 blue:102.0 / 255.0 alpha:1] forState:UIControlStateNormal]; 98 | } 99 | [whiteView addSubview:button]; 100 | [button addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside]; 101 | button.tag = 100 + i; 102 | } 103 | 104 | //文本提示 105 | UILabel *titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 120, 20)]; 106 | titleLabel.center = whiteView.center; 107 | titleLabel.text = @"选择预约时间"; 108 | titleLabel.textAlignment = NSTextAlignmentCenter; 109 | titleLabel.textColor = [UIColor colorWithRed:34.0/255 green:34.0/255 blue:34.0/255 alpha:1]; 110 | titleLabel.font = [UIFont systemFontOfSize:15.0f]; 111 | [whiteView addSubview:titleLabel]; 112 | 113 | //分割线 114 | UIView *line = [[UIView alloc]initWithFrame:CGRectMake(0, 49, [UIScreen mainScreen].bounds.size.width, 1)]; 115 | line.backgroundColor = [UIColor colorWithRed:230.0/255 green:230.0/255 blue:230.0/255 alpha:1]; 116 | [whiteView addSubview:line]; 117 | 118 | //pickerView 119 | UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 50, [UIScreen mainScreen].bounds.size.width, 210)]; 120 | pickerView.delegate = self; 121 | pickerView.dataSource = self; 122 | pickerView.backgroundColor = [UIColor whiteColor]; 123 | [self.contentView addSubview:pickerView]; 124 | } 125 | 126 | #pragma mark - Public 127 | - (void)show {//pickerView出现 128 | 129 | if (self.superView) { 130 | [self.superView addSubview:self]; 131 | } else { 132 | [[UIApplication sharedApplication].keyWindow addSubview:self]; 133 | } 134 | [UIView animateWithDuration:0.4 animations:^{ 135 | self.contentView.frame = CGRectMake(0, [UIScreen mainScreen].bounds.size.height - self.contentView.bounds.size.height, [UIScreen mainScreen].bounds.size.width, self.contentView.bounds.size.height); 136 | }]; 137 | } 138 | 139 | - (void)dismiss {//pickerView消失 140 | 141 | [UIView animateWithDuration:0.4 animations:^{ 142 | self.contentView.center = CGPointMake([UIScreen mainScreen].bounds.size.width / 2, self.contentView.center.y + self.contentView.frame.size.height); 143 | } completion:^(BOOL finished) { 144 | [self removeFromSuperview]; 145 | }]; 146 | } 147 | 148 | 149 | #pragma mark - Event Response 150 | - (void)buttonAction:(UIButton *)sender { 151 | if (sender.tag == 100) {//取消 152 | [self dismiss]; 153 | } else {//确定 154 | if (self.returnBlock) { 155 | QFDateModel *dateModel = self.dataSourceModel.dateArray[self.selectedDateIndex]; 156 | 157 | QFHourModel *hourModel; 158 | if (self.selectedDateIndex == 0) {//选中的今天 159 | hourModel = self.dataSourceModel.todayHourArray[self.selectedHourIndex]; 160 | } else { 161 | hourModel = self.dataSourceModel.hourArray[self.selectedHourIndex]; 162 | } 163 | 164 | QFMinuteModel *minModel; 165 | if (self.selectedHourIndex == 0 && self.selectedDateIndex == 0) {//选中的今天的第一个小时 166 | minModel = self.dataSourceModel.todayMinuteArray[self.selectedMinuteIndex]; 167 | } else { 168 | minModel = self.dataSourceModel.minuteArray[self.selectedMinuteIndex]; 169 | } 170 | 171 | NSString *returnStr = [NSString stringWithFormat:@"%@ %@:%@",dateModel.dateString,hourModel.hourString,minModel.minuteString]; 172 | self.returnBlock(returnStr); 173 | } 174 | [self dismiss]; 175 | } 176 | } 177 | 178 | #pragma mark - UIPickerViewDataSource UIPickerViewDelegate 179 | - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { 180 | return 3; 181 | } 182 | 183 | - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { 184 | if (component == 0) { 185 | return self.dataSourceModel.dateArray.count; 186 | } else if (component == 1) { 187 | if (self.selectedDateIndex == 0) {//选中的今天 188 | return self.dataSourceModel.todayHourArray.count; 189 | } else { 190 | return self.dataSourceModel.hourArray.count; 191 | } 192 | } else { 193 | if (self.selectedHourIndex == 0 && self.selectedDateIndex == 0) {//选中的今天的第一个小时 194 | return self.dataSourceModel.todayMinuteArray.count; 195 | } else { 196 | return self.dataSourceModel.minuteArray.count; 197 | } 198 | } 199 | } 200 | 201 | - (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component { 202 | if (component == 0) { 203 | return [UIScreen mainScreen].bounds.size.width / 2; 204 | } else { 205 | return [UIScreen mainScreen].bounds.size.width / 5; 206 | } 207 | } 208 | 209 | - (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UILabel *)recycledLabel { 210 | if (!recycledLabel) { 211 | recycledLabel = [[UILabel alloc] init]; 212 | } 213 | recycledLabel.textAlignment = NSTextAlignmentCenter; 214 | [recycledLabel setFont:[UIFont systemFontOfSize:18]]; 215 | recycledLabel.textColor = [UIColor colorWithRed:34.0f / 255.0f green:34.0f / 255.0f blue:34.0f / 255.0f alpha:1.0f]; 216 | 217 | if (component == 0) { 218 | QFDateModel *dateModel = self.dataSourceModel.dateArray[row]; 219 | recycledLabel.text = dateModel.showDateString; 220 | } else if (component == 1) { 221 | QFHourModel *hourModel; 222 | if (self.selectedDateIndex == 0) {//选中的今天 223 | hourModel = self.dataSourceModel.todayHourArray[row]; 224 | } else { 225 | hourModel = self.dataSourceModel.hourArray[row]; 226 | } 227 | recycledLabel.text = hourModel.showHourString; 228 | } else { 229 | QFMinuteModel *minModel; 230 | if (self.selectedHourIndex == 0 && self.selectedDateIndex == 0) {//选中的今天的第一个小时 231 | minModel = self.dataSourceModel.todayMinuteArray[row]; 232 | } else { 233 | minModel = self.dataSourceModel.minuteArray[row]; 234 | } 235 | recycledLabel.text = minModel.showMinuteString; 236 | } 237 | 238 | return recycledLabel; 239 | 240 | } 241 | 242 | - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { 243 | if (component == 0) { 244 | self.selectedDateIndex = row; 245 | self.selectedHourIndex = 0; 246 | self.selectedMinuteIndex = 0; 247 | [pickerView selectRow:0 inComponent:1 animated:YES]; 248 | [pickerView selectRow:0 inComponent:2 animated:YES]; 249 | } else if (component == 1) { 250 | self.selectedHourIndex = row; 251 | self.selectedMinuteIndex = 0; 252 | [pickerView selectRow:0 inComponent:2 animated:YES]; 253 | } else { 254 | self.selectedMinuteIndex = row; 255 | } 256 | [pickerView reloadAllComponents]; 257 | } 258 | 259 | 260 | @end 261 | -------------------------------------------------------------------------------- /QFDatePickerView/QFTimerPicker/Uitils/QFTimerUtil.h: -------------------------------------------------------------------------------- 1 | // 2 | // QFUtil.h 3 | // QFTimerPicker 4 | // 5 | // Created by 情风 on 2018/11/19. 6 | // Copyright © 2018年 qingfengiOS. All rights reserved. 7 | // 8 | 9 | #import 10 | @class QFTimerDataSourceModel; 11 | 12 | @interface QFTimerUtil : NSObject 13 | 14 | /** 15 | 获取pickerView数据源 16 | 17 | @return pickerView数据源 18 | */ 19 | + (QFTimerDataSourceModel *)configDataSource; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /QFDatePickerView/QFTimerPicker/Uitils/QFTimerUtil.m: -------------------------------------------------------------------------------- 1 | // 2 | // QFUtil.m 3 | // QFTimerPicker 4 | // 5 | // Created by 情风 on 2018/11/19. 6 | // Copyright © 2018年 qingfengiOS. All rights reserved. 7 | // 8 | 9 | #import "QFTimerUtil.h" 10 | #import "QFTimerDataSourceModel.h" 11 | #import "QFDateModel.h" 12 | #import "QFHourModel.h" 13 | #import "QFMinuteModel.h" 14 | 15 | static NSDateFormatter *_dateFormatter; 16 | 17 | static NSInteger const kBenginTimeDely = 20;//数据源的开始时间是当前时间的kBenginTimeDely分钟 并且向上取整 18 | static NSInteger const kTimeInterval = 10;//时间间隔 默认10分钟一个刻度 19 | static NSInteger const kDays = 3;//从今天起能选择多少天 默认3天 20 | 21 | @implementation QFTimerUtil 22 | 23 | + (void)load { 24 | if (!_dateFormatter) { 25 | _dateFormatter = [[NSDateFormatter alloc] init]; 26 | } 27 | } 28 | 29 | #pragma mark - Public 30 | + (QFTimerDataSourceModel *)configDataSource { 31 | 32 | QFTimerDataSourceModel *dataSourceModel = [QFTimerDataSourceModel new]; 33 | 34 | NSMutableArray *dateArray = [NSMutableArray array];//日期数据源 35 | NSMutableArray *todayHourArray = [NSMutableArray array];//当天的小时数据源 36 | NSMutableArray *todayMinuteArray = [NSMutableArray array];//当天的分钟数据源 37 | NSMutableArray *hourArray = [NSMutableArray array];//非当天的小时数据源 38 | NSMutableArray *minuteArray = [NSMutableArray array];//非当天的分钟数据源 39 | 40 | NSString *beginTime = [self getTimerAfterCurrentTime:kBenginTimeDely];//开始时间(也就是当前时间20分钟后) 41 | NSInteger currentMin = [self getMString:beginTime]; 42 | if (currentMin % kTimeInterval != 0) { 43 | beginTime = [self getTimerAfterTime:beginTime periodMin:(kTimeInterval - currentMin % kTimeInterval)];//开始时间向上取整 44 | } 45 | NSDate *currentDate = [NSDate date]; 46 | NSDate *appointDate; 47 | NSTimeInterval oneDay = 24 * 60 * 60; 48 | for (int i = 0; i < kDays; i++) { 49 | appointDate = [currentDate initWithTimeIntervalSinceNow: oneDay * i]; 50 | NSString *nextDateStr = [self getTomorrowDay:appointDate]; 51 | NSString *week = [self currentWeek:nextDateStr type:NO];//获取星期几 52 | 53 | QFDateModel *model = [[QFDateModel alloc]init]; 54 | model.dateString = nextDateStr.length > 10 ? [nextDateStr substringToIndex:10] : nextDateStr;//实际日期 55 | model.showDateString = [NSString stringWithFormat:@"%@ %@",[self getMDStringByString:nextDateStr],week];//展示的日期 56 | [dateArray addObject:model]; 57 | } 58 | 59 | 60 | NSInteger beginHour = [self getHString:beginTime]; 61 | for (NSInteger i = beginHour; i < 24 ; i++) { 62 | QFHourModel *model = [[QFHourModel alloc]init]; 63 | if (i < 10) { 64 | model.hourString = [NSString stringWithFormat:@"0%ld",i]; 65 | model.showHourString = [NSString stringWithFormat:@"%ld点",i]; 66 | } else { 67 | model.hourString = [NSString stringWithFormat:@"%ld",i]; 68 | model.showHourString = [NSString stringWithFormat:@"%ld点",i]; 69 | } 70 | [todayHourArray addObject:model]; 71 | } 72 | 73 | for (NSInteger i = 0; i < 24 ; i++) { 74 | QFHourModel *model = [[QFHourModel alloc]init]; 75 | if (i < 10) { 76 | model.hourString = [NSString stringWithFormat:@"0%ld",i]; 77 | model.showHourString = [NSString stringWithFormat:@"%ld点",i]; 78 | } else { 79 | model.hourString = [NSString stringWithFormat:@"%ld",i]; 80 | model.showHourString = [NSString stringWithFormat:@"%ld点",i]; 81 | } 82 | [hourArray addObject:model]; 83 | } 84 | 85 | NSInteger beginMin = [self getMString:beginTime]; 86 | NSInteger minStart = beginMin / kTimeInterval; 87 | 88 | for (NSInteger i = minStart; i < 60 / kTimeInterval; i++) { 89 | QFMinuteModel *model = [[QFMinuteModel alloc]init]; 90 | if (i * kTimeInterval < 10) { 91 | model.minuteString = [NSString stringWithFormat:@"0%ld",(long)i * kTimeInterval]; 92 | model.showMinuteString = [NSString stringWithFormat:@"0%ld分",(long)i * kTimeInterval]; 93 | } else { 94 | model.minuteString = [NSString stringWithFormat:@"%ld",i * kTimeInterval]; 95 | model.showMinuteString = [NSString stringWithFormat:@"%ld分",i * kTimeInterval]; 96 | } 97 | 98 | [todayMinuteArray addObject:model]; 99 | } 100 | 101 | for (NSInteger i = 0; i < 60 / kTimeInterval; i++) { 102 | QFMinuteModel *model = [[QFMinuteModel alloc]init]; 103 | if (i * kTimeInterval< 10) { 104 | model.minuteString = [NSString stringWithFormat:@"0%ld",(long)i * kTimeInterval]; 105 | model.showMinuteString = [NSString stringWithFormat:@"0%ld分",(long)i * kTimeInterval]; 106 | } else { 107 | model.minuteString = [NSString stringWithFormat:@"%ld",i * kTimeInterval]; 108 | model.showMinuteString = [NSString stringWithFormat:@"%ld分",i * kTimeInterval]; 109 | } 110 | 111 | [minuteArray addObject:model]; 112 | } 113 | 114 | dataSourceModel.dateArray = dateArray; 115 | 116 | dataSourceModel.hourArray = hourArray; 117 | dataSourceModel.minuteArray = minuteArray; 118 | 119 | dataSourceModel.todayHourArray = todayHourArray; 120 | dataSourceModel.todayMinuteArray = todayMinuteArray; 121 | 122 | return dataSourceModel; 123 | } 124 | 125 | #pragma mark - Private 126 | + (NSString *)getTomorrowDay:(NSDate *)aDate { 127 | NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; 128 | NSDateComponents *components = [gregorian components:NSCalendarUnitWeekday | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:aDate]; 129 | [components setDay:[components day]]; 130 | NSDate *beginningOfWeek = [gregorian dateFromComponents:components]; 131 | [_dateFormatter setDateFormat:@"yyyy-MM-dd"]; 132 | return [_dateFormatter stringFromDate:beginningOfWeek]; 133 | } 134 | ///得到当前日期 135 | + (NSString *)getCurrentDateStr { 136 | 137 | //获取当前时间,日期 138 | NSDate *currentDate = [NSDate date]; 139 | [_dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm"]; 140 | NSString *dateString = [_dateFormatter stringFromDate:currentDate]; 141 | 142 | return dateString; 143 | } 144 | 145 | /** 146 | NSString 转 NSDate 147 | 148 | @param string NSString 149 | @return NSDate 150 | */ 151 | + (NSDate *)stringToDate:(NSString *)string { 152 | [_dateFormatter setDateFormat:@"yyyy-MM-dd"]; 153 | NSDate *date = [_dateFormatter dateFromString:string]; 154 | return date; 155 | } 156 | 157 | /** 158 | Date转String 159 | 160 | @param date NSDate 161 | @return yyyy-MM-dd 162 | */ 163 | + (NSString *)dateToString:(NSDate *)date { 164 | [_dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm"]; 165 | NSString *strDate = [_dateFormatter stringFromDate:date]; 166 | return strDate; 167 | } 168 | 169 | /** 170 | 根据日期计算星期几 171 | 172 | @param date 日期 173 | @param type YES 为周几 NO 为星期几 174 | @return 周几 175 | */ 176 | + (NSString *)currentWeek:(NSString *)date type:(BOOL)type { 177 | 178 | if ([[date substringToIndex:10] isEqualToString:[[self getCurrentDateStr] substringToIndex:10]]) { 179 | return @"今天"; 180 | } 181 | 182 | NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; 183 | 184 | NSDateComponents *comps = [[NSDateComponents alloc] init]; 185 | NSInteger unitFlags = NSCalendarUnitWeekday; 186 | comps = [calendar components:unitFlags fromDate:[self stringToDate:date]]; 187 | 188 | NSString *week = @""; 189 | if (type) { 190 | switch (comps.weekday) { 191 | case 1:week = @"周日";break; 192 | case 2:week = @"周一";break; 193 | case 3:week = @"周二";break; 194 | case 4:week = @"周三";break; 195 | case 5:week = @"周四";break; 196 | case 6:week = @"周五";break; 197 | case 7:week = @"周六";break; 198 | default:break; 199 | } 200 | }else { 201 | switch (comps.weekday) { 202 | case 1:week = @"星期天";break; 203 | case 2:week = @"星期一";break; 204 | case 3:week = @"星期二";break; 205 | case 4:week = @"星期三";break; 206 | case 5:week = @"星期四";break; 207 | case 6:week = @"星期五";break; 208 | case 7:week = @"星期六";break; 209 | default:break; 210 | } 211 | } 212 | return week; 213 | } 214 | 215 | /** 216 | 计算X天后的日期 217 | 218 | @param nowDateString yyyy-MM-dd 219 | @param aDay 多少天后 220 | @return yyyy-MM-dd 221 | */ 222 | + (NSString *)distanceDate:(NSString *)nowDateString aDay:(NSInteger)aDay { 223 | 224 | NSDate *date = [self stringToDate:nowDateString]; 225 | NSDateComponents *comp = [[NSDateComponents alloc] init]; 226 | comp.day = aDay; 227 | NSDate *newDate = [[NSCalendar currentCalendar] dateByAddingComponents:comp toDate:date options:0]; 228 | 229 | return [self dateToString:newDate]; 230 | } 231 | /** 232 | * 把完整时间变成 XX月XX日 233 | * 234 | * @param dateString 完整返回时间 235 | * 236 | * @return XX月XX日 237 | */ 238 | + (NSString *)getMDStringByString:(NSString *)dateString { 239 | if (dateString.length >= 10) { 240 | NSString *month = [dateString substringWithRange:NSMakeRange(5, 2)]; 241 | NSString *day = [dateString substringWithRange:NSMakeRange(8, 2)]; 242 | return [NSString stringWithFormat:@"%@月%@日",month,day]; 243 | } else { 244 | return @""; 245 | } 246 | return @""; 247 | } 248 | 249 | /** 250 | * 取小时数 251 | * 252 | * @param dateString 完整返回时间 253 | * 254 | * @return XX 255 | */ 256 | + (NSInteger)getHString:(NSString *)dateString { 257 | if (dateString.length >= 13) { 258 | return [[dateString substringWithRange:NSMakeRange(11, 2)] integerValue]; 259 | } else { 260 | return 0; 261 | } 262 | } 263 | 264 | /** 265 | * 取分钟数 266 | * 267 | * @param dateString 完整返回时间 268 | * 269 | * @return XX 270 | */ 271 | + (NSInteger)getMString:(NSString *)dateString { 272 | if (dateString.length >= 16) { 273 | return [[dateString substringWithRange:NSMakeRange(14, 2)] integerValue]; 274 | } else { 275 | return 0; 276 | } 277 | } 278 | /** 279 | 获取当前时间X分钟后的时间 280 | 281 | @param periodMin 需要的是多少分钟后的时间 282 | @return 当前时间X分钟之后的时间字符串 283 | */ 284 | + (NSString *)getTimerAfterCurrentTime:(NSInteger)periodMin { 285 | [_dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm"]; 286 | NSString *resultStr = [_dateFormatter stringFromDate:[NSDate dateWithTimeIntervalSinceNow:periodMin * 60]]; 287 | return resultStr; 288 | } 289 | 290 | /** 291 | 获取指定时间X分钟后的时间 292 | 293 | @param periodMin 需要的是多少分钟后的时间 294 | @return 指定时间X分钟后的时间字符串 295 | */ 296 | + (NSString *)getTimerAfterTime:(NSString *)time periodMin:(NSInteger)periodMin { 297 | [_dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm"]; 298 | NSDate *date = [_dateFormatter dateFromString:time]; 299 | NSString *resultStr = [_dateFormatter stringFromDate:[date initWithTimeInterval:periodMin*60 sinceDate:date]]; 300 | return resultStr; 301 | } 302 | 303 | @end 304 | -------------------------------------------------------------------------------- /QFDatePickerView/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // dateDemo 4 | // 5 | // Created by 情风 on 2017/1/12. 6 | // Copyright © 2017年 情风. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | @end 14 | 15 | -------------------------------------------------------------------------------- /QFDatePickerView/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // dateDemo 4 | // 5 | // Created by 情风 on 2017/1/12. 6 | // Copyright © 2017年 情风. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | #import "QFDatePickerView.h" 12 | #import "QFTimePickerView.h" 13 | #import "QFTimerPicker.h" 14 | 15 | @interface ViewController () 16 | 17 | @end 18 | 19 | @implementation ViewController 20 | 21 | - (void)viewDidLoad { 22 | [super viewDidLoad]; 23 | 24 | } 25 | 26 | - (IBAction)showYearSelectView:(id)sender { 27 | 28 | QFDatePickerView *datePickerView = [[QFDatePickerView alloc]initYearPickerWithView:self.view response:^(NSString *str) { 29 | NSString *string = str; 30 | NSLog(@"str = %@",string); 31 | }]; 32 | [datePickerView show]; 33 | } 34 | 35 | - (IBAction)showDatePickerView:(id)sender { 36 | 37 | QFDatePickerView *datePickerView = [[QFDatePickerView alloc]initDatePackerWithSUperView:self.view response:^(NSString *str) { 38 | NSString *string = str; 39 | NSLog(@"str = %@",string); 40 | }]; 41 | [datePickerView show]; 42 | } 43 | 44 | - (IBAction)showTimePickerVierw:(id)sender { 45 | 46 | QFTimePickerView *pickerView = [[QFTimePickerView alloc]initDatePackerWithStartHour:@"18" endHour:@"12" period:5 response:^(NSString *str) { 47 | NSString *string = str; 48 | NSLog(@"str = %@",string); 49 | }]; 50 | [pickerView show]; 51 | } 52 | 53 | - (IBAction)chooseDate:(UIButton *)sender { 54 | QFTimerPicker *picker = [[QFTimerPicker alloc]initWithSuperView:self.view response:^(NSString *selectedStr) { 55 | NSLog(@"%@",selectedStr); 56 | [sender setTitle:selectedStr forState:UIControlStateNormal]; 57 | 58 | }]; 59 | 60 | [picker show]; 61 | } 62 | @end 63 | -------------------------------------------------------------------------------- /QFDatePickerView/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // QFDatePickerView 4 | // 5 | // Created by 建讯通 on 2017/1/13. 6 | // Copyright © 2017年 情风. 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 | -------------------------------------------------------------------------------- /QFDatePickerViewTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /QFDatePickerViewTests/QFDatePickerViewTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // QFDatePickerViewTests.m 3 | // QFDatePickerViewTests 4 | // 5 | // Created by 建讯通 on 2017/1/13. 6 | // Copyright © 2017年 情风. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface QFDatePickerViewTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation QFDatePickerViewTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /QFDatePickerViewUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /QFDatePickerViewUITests/QFDatePickerViewUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // QFDatePickerViewUITests.m 3 | // QFDatePickerViewUITests 4 | // 5 | // Created by 建讯通 on 2017/1/13. 6 | // Copyright © 2017年 情风. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface QFDatePickerViewUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation QFDatePickerViewUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 前言 2 | 在日常开发过程中,时间选择器的使用场景应该是比较高的,而且各个场景的具体需求也各式各样,比如一些场景中,只需要选择年月,有的需要包含“至今”,有的选择时间,有的需要选择年月日和时分,然而这些都需要自定义数据源,这里把自己遇到过的类型做了一个总结和记录。 3 | 4 | ## 年份选择 5 | 数据源1970至今,最后根据具体需求判断是否需要添加"至今"数据源,效果如下: 6 | 7 | ![year](https://upload-images.jianshu.io/upload_images/2598795-e3ecd95c3700ab82.png) 8 | 9 | ## 年和月份选择 10 | 年份数据源1970至今,月份为当年的最大月份,当切换到其他年份时,月份数据源变更为1~12月,当选择到“至今”时,月份数据为空,效果如下: 11 | 12 | ![year&month](https://upload-images.jianshu.io/upload_images/2598795-496f71b93cbd8ad2.png) 13 | 14 | ## 时和分选择 15 | 这里的起止时间节点根据初始化时传入的数据进行配置,分钟的间隔数也由调用者动态配置 16 | ![hour&min](https://upload-images.jianshu.io/upload_images/2598795-207f1ba8fdd35d41.png) 17 | 18 | ## 仿滴滴时间选择 19 | 这个picker是这几种类型中相对最复杂的一种,牵涉到数据源的完全计算,NSdate和NSString的相互转换,pickView样式的高度自定义。之前已经写过一篇,这里就不做copy了,详情请看:[iOS仿滴滴预约用车时间选择器](https://juejin.im/post/5bf7a4ce51882550d05ca29a) 20 | 21 | ## 使用方式 22 | 各个picker的数据源,基本没有难点,有兴趣的可自行查看[源码](https://github.com/qingfengiOS/QFDatePickerView.git)。 23 | 24 | 稍微说说使用方式,下载源码,拖入工程,或者直接使用cocoapods:pod 'QFDatePicker' 25 | 26 | 调用对应的初始化方法(init...)和show方法,以年份为例: 27 | 28 | ``` 29 | QFDatePickerView *datePickerView = [[QFDatePickerView alloc]initYearPickerWithView:self.view response:^(NSString *str) { 30 | NSString *string = str; 31 | NSLog(@"str = %@",string); 32 | }]; 33 | 34 | [datePickerView show]; 35 | ``` 36 | 选中的时间在block中处理,其他调用类似,相信睿智的您一眼就能看明白。 37 | 这篇主要是对一年前的文章做一次整理(之前的确实有点辣眼睛),希望看到的朋友轻喷。 38 | 39 | 最后,希望各位大神指点,如果对您有用的话请顺手给个star 40 | [演示Demo](https://github.com/qingfengiOS/QFDatePickerView) 41 | [cocoaPods安装](https://github.com/qingfengiOS/QFDatePicker) 42 | 43 | 44 | --------------------------------------------------------------------------------