├── .gitignore ├── JX_GCDTimer ├── JX_GCDTimerManager.h └── JX_GCDTimerManager.m ├── JX_GCDTimerDemo ├── JX_GCDTimer.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcuserdata │ │ └── Joeyxu.xcuserdatad │ │ └── xcschemes │ │ ├── JX_GCDTimer.xcscheme │ │ └── xcschememanagement.plist └── JX_GCDTimer │ ├── .DS_Store │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard │ ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Info.plist │ ├── ViewController.h │ ├── ViewController.m │ └── main.m ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | # CocoaPods 32 | # 33 | # We recommend against adding the Pods directory to your .gitignore. However 34 | # you should judge for yourself, the pros and cons are mentioned at: 35 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 36 | # 37 | # Pods/ 38 | 39 | # Carthage 40 | # 41 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 42 | # Carthage/Checkouts 43 | 44 | Carthage/Build 45 | 46 | # fastlane 47 | # 48 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 49 | # screenshots whenever they are needed. 50 | # For more information about the recommended setup visit: 51 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 52 | 53 | fastlane/report.xml 54 | fastlane/Preview.html 55 | fastlane/screenshots/**/*.png 56 | fastlane/test_output 57 | 58 | # Code Injection 59 | # 60 | # After new code Injection tools there's a generated folder /iOSInjectionProject 61 | # https://github.com/johnno1962/injectionforxcode 62 | 63 | iOSInjectionProject/ 64 | -------------------------------------------------------------------------------- /JX_GCDTimer/JX_GCDTimerManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // JX_GCDTimer.h 3 | // TimerComparison 4 | // 5 | // Created by Joeyxu on 6/12/15. 6 | // Copyright (c) 2015 com.tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface JX_GCDTimerManager : NSObject 12 | 13 | + (JX_GCDTimerManager *)sharedInstance; 14 | 15 | /** 16 | 启动一个timer,默认精度为0.01秒。 17 | 18 | @param timerName timer的名称,作为唯一标识。 19 | @param interval 执行的时间间隔。 20 | @param queue timer将被放入的队列,也就是最终action执行的队列。传入nil将自动放到一个子线程队列中。 21 | @param repeats timer是否循环调用。 22 | @param fireInstantly timer的第一次执行是否立刻触发,否则会等待interval的时长才会第一次执行。 23 | @param action 时间间隔到点时执行的block。 24 | */ 25 | - (void)scheduledDispatchTimerWithName:(NSString *)timerName 26 | timeInterval:(double)interval 27 | queue:(dispatch_queue_t)queue 28 | repeats:(BOOL)repeats 29 | fireInstantly:(BOOL)fireInstantly 30 | action:(dispatch_block_t)dispatchBlock; 31 | 32 | /** 33 | 撤销某个timer。 34 | 35 | @param timerName timer的名称,作为唯一标识。 36 | */ 37 | - (void)cancelTimerWithName:(NSString *)timerName; 38 | 39 | 40 | /** 41 | * 是否存在某个名称标识的timer。 42 | * 43 | * @param timerName timer的唯一名称标识。 44 | * @param 查询结束回调。doExist==YES表示存在,反之。 45 | */ 46 | - (void)checkExistTimer:(NSString *)timerName 47 | completion:(void (^)(BOOL doExist))completion; 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /JX_GCDTimer/JX_GCDTimerManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // JX_GCDTimer.m 3 | // TimerComparison 4 | // 5 | // Created by Joeyxu on 6/12/15. 6 | // Copyright (c) 2015 com.tencent. All rights reserved. 7 | // 8 | 9 | #import "JX_GCDTimerManager.h" 10 | 11 | @interface JX_GCDTimerManager() 12 | @property (nonatomic, strong) NSMutableDictionary *timerContainer; 13 | @property (nonatomic, strong) dispatch_queue_t queue; 14 | @end 15 | 16 | @implementation JX_GCDTimerManager 17 | 18 | #pragma mark - Public Method 19 | 20 | + (JX_GCDTimerManager *)sharedInstance { 21 | static JX_GCDTimerManager *_gcdTimerManager = nil; 22 | static dispatch_once_t onceToken; 23 | 24 | dispatch_once(&onceToken,^{ 25 | _gcdTimerManager = [[JX_GCDTimerManager alloc] init]; 26 | }); 27 | 28 | return _gcdTimerManager; 29 | } 30 | 31 | - (instancetype)init { 32 | self = [super init]; 33 | if (self) { 34 | dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT, QOS_CLASS_USER_INITIATED, 0); 35 | dispatch_queue_t queue = dispatch_queue_create("com.JX_GCDTimerManager.queue", attr); 36 | _queue = queue; 37 | _timerContainer = [NSMutableDictionary new]; 38 | } 39 | return self; 40 | } 41 | 42 | - (void)scheduledDispatchTimerWithName:(NSString *)timerName 43 | timeInterval:(double)interval 44 | queue:(dispatch_queue_t)queue 45 | repeats:(BOOL)repeats 46 | fireInstantly:(BOOL)fireInstantly 47 | action:(dispatch_block_t)dispatchBlock { 48 | if (!timerName || timerName.length == 0 || !dispatchBlock) return; 49 | 50 | if (nil == queue) 51 | queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 52 | 53 | dispatch_barrier_async(self.queue, ^{ 54 | dispatch_source_t timer = [self.timerContainer objectForKey:timerName]; 55 | if (!timer) { 56 | timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); 57 | [self.timerContainer setObject:timer forKey:timerName]; 58 | dispatch_resume(timer); 59 | } 60 | 61 | if (repeats && fireInstantly) { 62 | dispatch_async(queue, dispatchBlock); 63 | } 64 | 65 | dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, interval * NSEC_PER_SEC), interval * NSEC_PER_SEC, 0.01 * NSEC_PER_SEC); 66 | dispatch_source_set_event_handler(timer, ^{ 67 | if (!repeats) { 68 | [self.timerContainer removeObjectForKey:timerName]; 69 | dispatch_source_cancel(timer); 70 | } 71 | 72 | dispatchBlock(); 73 | }); 74 | }); 75 | } 76 | 77 | - (void)cancelTimerWithName:(NSString *)timerName { 78 | dispatch_barrier_async(self.queue, ^{ 79 | dispatch_source_t timer = [self.timerContainer objectForKey:timerName]; 80 | 81 | if (!timer) { 82 | return; 83 | } 84 | 85 | [self.timerContainer removeObjectForKey:timerName]; 86 | dispatch_source_cancel(timer); 87 | }); 88 | } 89 | 90 | - (void)checkExistTimer:(NSString *)timerName completion:(void (^)(BOOL))completion { 91 | dispatch_async(self.queue, ^{ 92 | if ([self.timerContainer objectForKey:timerName]) { 93 | completion(YES); 94 | } else { 95 | completion(NO); 96 | } 97 | }); 98 | } 99 | 100 | @end 101 | -------------------------------------------------------------------------------- /JX_GCDTimerDemo/JX_GCDTimer.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8D5980B91F65084000BEDD70 /* JX_GCDTimerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D5980B81F65084000BEDD70 /* JX_GCDTimerManager.m */; }; 11 | 8DE607DA1B33070300BCDEE4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DE607D91B33070300BCDEE4 /* main.m */; }; 12 | 8DE607DD1B33070300BCDEE4 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DE607DC1B33070300BCDEE4 /* AppDelegate.m */; }; 13 | 8DE607E01B33070300BCDEE4 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DE607DF1B33070300BCDEE4 /* ViewController.m */; }; 14 | 8DE607E31B33070300BCDEE4 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8DE607E11B33070300BCDEE4 /* Main.storyboard */; }; 15 | 8DE607E51B33070300BCDEE4 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8DE607E41B33070300BCDEE4 /* Images.xcassets */; }; 16 | 8DE607E81B33070300BCDEE4 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8DE607E61B33070300BCDEE4 /* LaunchScreen.xib */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | 8D5980B71F65084000BEDD70 /* JX_GCDTimerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JX_GCDTimerManager.h; sourceTree = ""; }; 21 | 8D5980B81F65084000BEDD70 /* JX_GCDTimerManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JX_GCDTimerManager.m; sourceTree = ""; }; 22 | 8DE607D41B33070300BCDEE4 /* JX_GCDTimer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JX_GCDTimer.app; sourceTree = BUILT_PRODUCTS_DIR; }; 23 | 8DE607D81B33070300BCDEE4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 24 | 8DE607D91B33070300BCDEE4 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 25 | 8DE607DB1B33070300BCDEE4 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 26 | 8DE607DC1B33070300BCDEE4 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 27 | 8DE607DE1B33070300BCDEE4 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 28 | 8DE607DF1B33070300BCDEE4 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 29 | 8DE607E21B33070300BCDEE4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 30 | 8DE607E41B33070300BCDEE4 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 31 | 8DE607E71B33070300BCDEE4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 32 | /* End PBXFileReference section */ 33 | 34 | /* Begin PBXFrameworksBuildPhase section */ 35 | 8DE607D11B33070300BCDEE4 /* Frameworks */ = { 36 | isa = PBXFrameworksBuildPhase; 37 | buildActionMask = 2147483647; 38 | files = ( 39 | ); 40 | runOnlyForDeploymentPostprocessing = 0; 41 | }; 42 | /* End PBXFrameworksBuildPhase section */ 43 | 44 | /* Begin PBXGroup section */ 45 | 8D5980B61F65084000BEDD70 /* JX_GCDTimer */ = { 46 | isa = PBXGroup; 47 | children = ( 48 | 8D5980B71F65084000BEDD70 /* JX_GCDTimerManager.h */, 49 | 8D5980B81F65084000BEDD70 /* JX_GCDTimerManager.m */, 50 | ); 51 | name = JX_GCDTimer; 52 | path = ../../JX_GCDTimer; 53 | sourceTree = ""; 54 | }; 55 | 8DE607CB1B33070200BCDEE4 = { 56 | isa = PBXGroup; 57 | children = ( 58 | 8DE607D61B33070300BCDEE4 /* JX_GCDTimer */, 59 | 8DE607D51B33070300BCDEE4 /* Products */, 60 | ); 61 | sourceTree = ""; 62 | }; 63 | 8DE607D51B33070300BCDEE4 /* Products */ = { 64 | isa = PBXGroup; 65 | children = ( 66 | 8DE607D41B33070300BCDEE4 /* JX_GCDTimer.app */, 67 | ); 68 | name = Products; 69 | sourceTree = ""; 70 | }; 71 | 8DE607D61B33070300BCDEE4 /* JX_GCDTimer */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | 8D5980B61F65084000BEDD70 /* JX_GCDTimer */, 75 | 8DE607DB1B33070300BCDEE4 /* AppDelegate.h */, 76 | 8DE607DC1B33070300BCDEE4 /* AppDelegate.m */, 77 | 8DE607DE1B33070300BCDEE4 /* ViewController.h */, 78 | 8DE607DF1B33070300BCDEE4 /* ViewController.m */, 79 | 8DE607E11B33070300BCDEE4 /* Main.storyboard */, 80 | 8DE607E41B33070300BCDEE4 /* Images.xcassets */, 81 | 8DE607E61B33070300BCDEE4 /* LaunchScreen.xib */, 82 | 8DE607D71B33070300BCDEE4 /* Supporting Files */, 83 | ); 84 | path = JX_GCDTimer; 85 | sourceTree = ""; 86 | }; 87 | 8DE607D71B33070300BCDEE4 /* Supporting Files */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | 8DE607D81B33070300BCDEE4 /* Info.plist */, 91 | 8DE607D91B33070300BCDEE4 /* main.m */, 92 | ); 93 | name = "Supporting Files"; 94 | sourceTree = ""; 95 | }; 96 | /* End PBXGroup section */ 97 | 98 | /* Begin PBXNativeTarget section */ 99 | 8DE607D31B33070300BCDEE4 /* JX_GCDTimer */ = { 100 | isa = PBXNativeTarget; 101 | buildConfigurationList = 8DE607F71B33070300BCDEE4 /* Build configuration list for PBXNativeTarget "JX_GCDTimer" */; 102 | buildPhases = ( 103 | 8DE607D01B33070300BCDEE4 /* Sources */, 104 | 8DE607D11B33070300BCDEE4 /* Frameworks */, 105 | 8DE607D21B33070300BCDEE4 /* Resources */, 106 | ); 107 | buildRules = ( 108 | ); 109 | dependencies = ( 110 | ); 111 | name = JX_GCDTimer; 112 | productName = JX_GCDTimer; 113 | productReference = 8DE607D41B33070300BCDEE4 /* JX_GCDTimer.app */; 114 | productType = "com.apple.product-type.application"; 115 | }; 116 | /* End PBXNativeTarget section */ 117 | 118 | /* Begin PBXProject section */ 119 | 8DE607CC1B33070200BCDEE4 /* Project object */ = { 120 | isa = PBXProject; 121 | attributes = { 122 | LastUpgradeCheck = 0630; 123 | ORGANIZATIONNAME = com.joeyxu; 124 | TargetAttributes = { 125 | 8DE607D31B33070300BCDEE4 = { 126 | CreatedOnToolsVersion = 6.3.1; 127 | }; 128 | }; 129 | }; 130 | buildConfigurationList = 8DE607CF1B33070200BCDEE4 /* Build configuration list for PBXProject "JX_GCDTimer" */; 131 | compatibilityVersion = "Xcode 3.2"; 132 | developmentRegion = English; 133 | hasScannedForEncodings = 0; 134 | knownRegions = ( 135 | en, 136 | Base, 137 | ); 138 | mainGroup = 8DE607CB1B33070200BCDEE4; 139 | productRefGroup = 8DE607D51B33070300BCDEE4 /* Products */; 140 | projectDirPath = ""; 141 | projectRoot = ""; 142 | targets = ( 143 | 8DE607D31B33070300BCDEE4 /* JX_GCDTimer */, 144 | ); 145 | }; 146 | /* End PBXProject section */ 147 | 148 | /* Begin PBXResourcesBuildPhase section */ 149 | 8DE607D21B33070300BCDEE4 /* Resources */ = { 150 | isa = PBXResourcesBuildPhase; 151 | buildActionMask = 2147483647; 152 | files = ( 153 | 8DE607E31B33070300BCDEE4 /* Main.storyboard in Resources */, 154 | 8DE607E81B33070300BCDEE4 /* LaunchScreen.xib in Resources */, 155 | 8DE607E51B33070300BCDEE4 /* Images.xcassets in Resources */, 156 | ); 157 | runOnlyForDeploymentPostprocessing = 0; 158 | }; 159 | /* End PBXResourcesBuildPhase section */ 160 | 161 | /* Begin PBXSourcesBuildPhase section */ 162 | 8DE607D01B33070300BCDEE4 /* Sources */ = { 163 | isa = PBXSourcesBuildPhase; 164 | buildActionMask = 2147483647; 165 | files = ( 166 | 8DE607E01B33070300BCDEE4 /* ViewController.m in Sources */, 167 | 8DE607DD1B33070300BCDEE4 /* AppDelegate.m in Sources */, 168 | 8D5980B91F65084000BEDD70 /* JX_GCDTimerManager.m in Sources */, 169 | 8DE607DA1B33070300BCDEE4 /* main.m in Sources */, 170 | ); 171 | runOnlyForDeploymentPostprocessing = 0; 172 | }; 173 | /* End PBXSourcesBuildPhase section */ 174 | 175 | /* Begin PBXVariantGroup section */ 176 | 8DE607E11B33070300BCDEE4 /* Main.storyboard */ = { 177 | isa = PBXVariantGroup; 178 | children = ( 179 | 8DE607E21B33070300BCDEE4 /* Base */, 180 | ); 181 | name = Main.storyboard; 182 | sourceTree = ""; 183 | }; 184 | 8DE607E61B33070300BCDEE4 /* LaunchScreen.xib */ = { 185 | isa = PBXVariantGroup; 186 | children = ( 187 | 8DE607E71B33070300BCDEE4 /* Base */, 188 | ); 189 | name = LaunchScreen.xib; 190 | sourceTree = ""; 191 | }; 192 | /* End PBXVariantGroup section */ 193 | 194 | /* Begin XCBuildConfiguration section */ 195 | 8DE607F51B33070300BCDEE4 /* Debug */ = { 196 | isa = XCBuildConfiguration; 197 | buildSettings = { 198 | ALWAYS_SEARCH_USER_PATHS = NO; 199 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 200 | CLANG_CXX_LIBRARY = "libc++"; 201 | CLANG_ENABLE_MODULES = YES; 202 | CLANG_ENABLE_OBJC_ARC = YES; 203 | CLANG_WARN_BOOL_CONVERSION = YES; 204 | CLANG_WARN_CONSTANT_CONVERSION = YES; 205 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 206 | CLANG_WARN_EMPTY_BODY = YES; 207 | CLANG_WARN_ENUM_CONVERSION = YES; 208 | CLANG_WARN_INT_CONVERSION = YES; 209 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 210 | CLANG_WARN_UNREACHABLE_CODE = YES; 211 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 212 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 213 | COPY_PHASE_STRIP = NO; 214 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 215 | ENABLE_STRICT_OBJC_MSGSEND = YES; 216 | GCC_C_LANGUAGE_STANDARD = gnu99; 217 | GCC_DYNAMIC_NO_PIC = NO; 218 | GCC_NO_COMMON_BLOCKS = YES; 219 | GCC_OPTIMIZATION_LEVEL = 0; 220 | GCC_PREPROCESSOR_DEFINITIONS = ( 221 | "DEBUG=1", 222 | "$(inherited)", 223 | ); 224 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 225 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 226 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 227 | GCC_WARN_UNDECLARED_SELECTOR = YES; 228 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 229 | GCC_WARN_UNUSED_FUNCTION = YES; 230 | GCC_WARN_UNUSED_VARIABLE = YES; 231 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 232 | MTL_ENABLE_DEBUG_INFO = YES; 233 | ONLY_ACTIVE_ARCH = YES; 234 | SDKROOT = iphoneos; 235 | }; 236 | name = Debug; 237 | }; 238 | 8DE607F61B33070300BCDEE4 /* Release */ = { 239 | isa = XCBuildConfiguration; 240 | buildSettings = { 241 | ALWAYS_SEARCH_USER_PATHS = NO; 242 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 243 | CLANG_CXX_LIBRARY = "libc++"; 244 | CLANG_ENABLE_MODULES = YES; 245 | CLANG_ENABLE_OBJC_ARC = YES; 246 | CLANG_WARN_BOOL_CONVERSION = YES; 247 | CLANG_WARN_CONSTANT_CONVERSION = YES; 248 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 249 | CLANG_WARN_EMPTY_BODY = YES; 250 | CLANG_WARN_ENUM_CONVERSION = YES; 251 | CLANG_WARN_INT_CONVERSION = YES; 252 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 253 | CLANG_WARN_UNREACHABLE_CODE = YES; 254 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 255 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 256 | COPY_PHASE_STRIP = NO; 257 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 258 | ENABLE_NS_ASSERTIONS = NO; 259 | ENABLE_STRICT_OBJC_MSGSEND = YES; 260 | GCC_C_LANGUAGE_STANDARD = gnu99; 261 | GCC_NO_COMMON_BLOCKS = YES; 262 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 263 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 264 | GCC_WARN_UNDECLARED_SELECTOR = YES; 265 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 266 | GCC_WARN_UNUSED_FUNCTION = YES; 267 | GCC_WARN_UNUSED_VARIABLE = YES; 268 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 269 | MTL_ENABLE_DEBUG_INFO = NO; 270 | SDKROOT = iphoneos; 271 | VALIDATE_PRODUCT = YES; 272 | }; 273 | name = Release; 274 | }; 275 | 8DE607F81B33070300BCDEE4 /* Debug */ = { 276 | isa = XCBuildConfiguration; 277 | buildSettings = { 278 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 279 | INFOPLIST_FILE = JX_GCDTimer/Info.plist; 280 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 281 | PRODUCT_NAME = "$(TARGET_NAME)"; 282 | }; 283 | name = Debug; 284 | }; 285 | 8DE607F91B33070300BCDEE4 /* Release */ = { 286 | isa = XCBuildConfiguration; 287 | buildSettings = { 288 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 289 | INFOPLIST_FILE = JX_GCDTimer/Info.plist; 290 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 291 | PRODUCT_NAME = "$(TARGET_NAME)"; 292 | }; 293 | name = Release; 294 | }; 295 | /* End XCBuildConfiguration section */ 296 | 297 | /* Begin XCConfigurationList section */ 298 | 8DE607CF1B33070200BCDEE4 /* Build configuration list for PBXProject "JX_GCDTimer" */ = { 299 | isa = XCConfigurationList; 300 | buildConfigurations = ( 301 | 8DE607F51B33070300BCDEE4 /* Debug */, 302 | 8DE607F61B33070300BCDEE4 /* Release */, 303 | ); 304 | defaultConfigurationIsVisible = 0; 305 | defaultConfigurationName = Release; 306 | }; 307 | 8DE607F71B33070300BCDEE4 /* Build configuration list for PBXNativeTarget "JX_GCDTimer" */ = { 308 | isa = XCConfigurationList; 309 | buildConfigurations = ( 310 | 8DE607F81B33070300BCDEE4 /* Debug */, 311 | 8DE607F91B33070300BCDEE4 /* Release */, 312 | ); 313 | defaultConfigurationIsVisible = 0; 314 | defaultConfigurationName = Release; 315 | }; 316 | /* End XCConfigurationList section */ 317 | }; 318 | rootObject = 8DE607CC1B33070200BCDEE4 /* Project object */; 319 | } 320 | -------------------------------------------------------------------------------- /JX_GCDTimerDemo/JX_GCDTimer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /JX_GCDTimerDemo/JX_GCDTimer.xcodeproj/xcuserdata/Joeyxu.xcuserdatad/xcschemes/JX_GCDTimer.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 77 | 83 | 84 | 85 | 86 | 87 | 88 | 94 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /JX_GCDTimerDemo/JX_GCDTimer.xcodeproj/xcuserdata/Joeyxu.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | JX_GCDTimer.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 8DE607D31B33070300BCDEE4 16 | 17 | primary 18 | 19 | 20 | 8DE607EC1B33070300BCDEE4 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /JX_GCDTimerDemo/JX_GCDTimer/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Joeyqiushi/JX_GCDTimer/1b6dab9d4a7b76be1fe09e3e19ddb3a6c1a2e875/JX_GCDTimerDemo/JX_GCDTimer/.DS_Store -------------------------------------------------------------------------------- /JX_GCDTimerDemo/JX_GCDTimer/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // JX_GCDTimer 4 | // 5 | // Created by Joeyxu on 6/18/15. 6 | // Copyright (c) 2015 com.joeyxu. 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 | -------------------------------------------------------------------------------- /JX_GCDTimerDemo/JX_GCDTimer/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // JX_GCDTimer 4 | // 5 | // Created by Joeyxu on 6/18/15. 6 | // Copyright (c) 2015 com.joeyxu. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /JX_GCDTimerDemo/JX_GCDTimer/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /JX_GCDTimerDemo/JX_GCDTimer/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /JX_GCDTimerDemo/JX_GCDTimer/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /JX_GCDTimerDemo/JX_GCDTimer/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.joeyxu.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /JX_GCDTimerDemo/JX_GCDTimer/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // JX_GCDTimer 4 | // 5 | // Created by Joeyxu on 6/18/15. 6 | // Copyright (c) 2015 com.joeyxu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /JX_GCDTimerDemo/JX_GCDTimer/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // JX_GCDTimer 4 | // 5 | // Created by Joeyxu on 6/18/15. 6 | // Copyright (c) 2015 com.joeyxu. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "JX_GCDTimerManager.h" 11 | 12 | @interface ViewController () 13 | @property (nonatomic, strong) NSTimer *timer; 14 | @end 15 | 16 | static NSString * const myTimer = @"MyTimer"; 17 | 18 | @implementation ViewController 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | 23 | /* 启动一个timer,每隔2秒执行一次。每次执行打印一条log记录,在执行到n==10的时候cancel掉timer。 */ 24 | // [self demoNSTimer]; 25 | [self demoGCDTimer]; 26 | 27 | /* 28 | * 苹果的开发人员应该发现了NSTimer比较严重的循环引用缺陷,所以在iOS10上提供了使用block的NSTimer接口: 29 | * + (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval 30 | * repeats:(BOOL)repeats 31 | * block:(void (^)(NSTimer *timer))block; 32 | */ 33 | // [self demoNSTimerAfteriOS10]; 34 | } 35 | 36 | - (void)demoNSTimer { 37 | self.timer = [NSTimer scheduledTimerWithTimeInterval:2.0 38 | target:self 39 | selector:@selector(doSomething) 40 | userInfo:nil 41 | repeats:YES]; 42 | } 43 | 44 | - (void)demoGCDTimer { 45 | __weak typeof(self) weakSelf = self; 46 | [[JX_GCDTimerManager sharedInstance] scheduledDispatchTimerWithName:myTimer 47 | timeInterval:2.0 48 | queue:dispatch_get_main_queue() 49 | repeats:YES 50 | fireInstantly:NO 51 | action:^{ 52 | [weakSelf doSomething]; 53 | }]; 54 | } 55 | 56 | - (void)demoNSTimerAfteriOS10 { 57 | __weak typeof(self) weakSelf = self; 58 | self.timer = [NSTimer scheduledTimerWithTimeInterval:2.0 59 | repeats:YES 60 | block:^(NSTimer * _Nonnull timer) { 61 | [weakSelf doSomething]; 62 | }]; 63 | } 64 | 65 | /* timer每次执行打印一条log记录,在执行到n==10的时候cancel掉timer */ 66 | - (void)doSomething { 67 | static NSUInteger n = 0; 68 | NSLog(@"myTimer runs %lu times!", (unsigned long)n++); 69 | 70 | if (n >= 10) { 71 | [self.timer invalidate]; 72 | [[JX_GCDTimerManager sharedInstance] cancelTimerWithName:myTimer]; 73 | } 74 | } 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /JX_GCDTimerDemo/JX_GCDTimer/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // JX_GCDTimer 4 | // 5 | // Created by Joeyxu on 6/18/15. 6 | // Copyright (c) 2015 com.joeyxu. 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 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Joeyqiushi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## JX_GCDTimerManager 2 | 3 | ![](https://img.shields.io/github/license/mashape/apistatus.svg) ![](https://img.shields.io/badge/platform-iOS-lightgrey.svg) ![](https://img.shields.io/badge/iOS-8.0%2B-blue.svg) 4 | 5 | JX_GCDTimerManager is a NSTimer like tool implemented using GCD. 6 | 7 | ## Usage 8 | 9 | 1. Add the source files `JX_GCDTimerManager.h` and `JX_GCDTimerManager.m` to your Xcode project. 10 | 2. Import `JX_GCDTimerManager.h` . 11 | 3. Use in you code. 12 | 13 | ``` 14 | __weak typeof(self) weakSelf = self; 15 | [[JX_GCDTimerManager sharedInstance] scheduledDispatchTimerWithName:@"myTime_hash" 16 | timeInterval:2.0 17 | queue:dispatch_get_main_queue() 18 | repeats:NO 19 | fireInstantly:NO 20 | action:^{ 21 | [weakSelf doSomething]; 22 | }]; 23 | ``` 24 | 25 | You can add or remove functions as you need. 26 | 27 | ## Requirements 28 | 29 | This component requires `iOS 8.0+`. 30 | 31 | ## Notice 32 | 33 | If you are using `JX_GCDTimerManager` as a singleton, you should watch out that timer with the same name could interfere each other, as the name is the unique key of the timer. Make sure to use unique names for timer instances. 34 | 35 | ## License 36 | 37 | JX_GCDTimerManager is provided under the MIT license. See LICENSE file for details. 38 | --------------------------------------------------------------------------------