1、GCD定时器实现的基础代码
1
2
3
4
5
6
| dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, <#dispatchQueue#>);
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, <#intervalInSeconds#> * NSEC_PER_SEC, <#leewayInSeconds#> * NSEC_PER_SEC);
dispatch_source_set_event_handler(timer, ^{
<#code to be executed when timer fires#>
});
dispatch_resume(timer); |
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, <#dispatchQueue#>);
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, <#intervalInSeconds#> * NSEC_PER_SEC, <#leewayInSeconds#> * NSEC_PER_SEC);
dispatch_source_set_event_handler(timer, ^{
<#code to be executed when timer fires#>
});
dispatch_resume(timer);
2、对其进行简单封装,使外部调用时传入间隔时间、重复次数、定时执行代码即可自动定时执行
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
| #import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface SATimer : NSObject
/**
创建并开启一个定时任务
@param interval 重复执行的间隔时间
@param count 重复次数
@param block 重复执行代码
@return 返回定时器的唯一标识
*/
+ (NSString *)timerWithInterval:(NSTimeInterval)interval repeatCount:(NSUInteger)count block:(void (^)(NSUInteger remainCount))block;
/**
根据定时器的唯一标识,停止定时器
@param timerId 定时器唯一标识
*/
+ (void)invalidateWithId:(NSString *)timerId;
@end
NS_ASSUME_NONNULL_END |
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface SATimer : NSObject
/**
创建并开启一个定时任务
@param interval 重复执行的间隔时间
@param count 重复次数
@param block 重复执行代码
@return 返回定时器的唯一标识
*/
+ (NSString *)timerWithInterval:(NSTimeInterval)interval repeatCount:(NSUInteger)count block:(void (^)(NSUInteger remainCount))block;
/**
根据定时器的唯一标识,停止定时器
@param timerId 定时器唯一标识
*/
+ (void)invalidateWithId:(NSString *)timerId;
@end
NS_ASSUME_NONNULL_END
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
| #import "SATimer.h"
static NSMutableDictionary *timerDictionary_;
static NSMutableDictionary *countDictionary_;
static dispatch_semaphore_t semaphore_;
@implementation SATimer
+ (void)initialize
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
semaphore_ = dispatch_semaphore_create(1);
timerDictionary_ = [NSMutableDictionary dictionary];
countDictionary_ = [NSMutableDictionary dictionary];
});
}
+ (NSString *)timerWithInterval:(NSTimeInterval)interval repeatCount:(NSUInteger)count block:(void (^)(NSUInteger remainCount))block;
{
if ((block == nil) || (count <= 0) || (interval <= 0)) return nil;
// gcd定时器基本实现
dispatch_queue_t queue = dispatch_queue_create("com.yusian.timer-queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, interval * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
NSString *timerId = [NSString stringWithFormat:@"%p", timer];
// 字典写入时的线程安全
dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER);
[timerDictionary_ setObject:timer forKey:timerId];
[countDictionary_ setObject:@(count) forKey:timerId];
dispatch_semaphore_signal(semaphore_);
// 执行定时任务
dispatch_source_set_event_handler(timer, ^{
NSNumber *count = [countDictionary_ objectForKey:timerId];
NSUInteger remainCount = count.unsignedIntegerValue;
block(--remainCount);
// 字典写入时的线程安全
dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER);
[countDictionary_ setObject:@(remainCount) forKey:timerId];
dispatch_semaphore_signal(semaphore_);
// 重复次数剩余量为0时自动退出
if (remainCount == 0) [self invalidateWithId:timerId];
});
dispatch_resume(timer);
return timerId;
}
+ (void)invalidateWithId:(NSString *)timerId
{
dispatch_source_t timer = [timerDictionary_ objectForKey:timerId];
if (timer == nil) return;
dispatch_source_cancel(timer);
[timerDictionary_ removeObjectForKey:timerId];
[countDictionary_ removeObjectForKey:timerId];
NSLog(@"SATimer invalidate - %@", timerId);
}
@end |
#import "SATimer.h"
static NSMutableDictionary *timerDictionary_;
static NSMutableDictionary *countDictionary_;
static dispatch_semaphore_t semaphore_;
@implementation SATimer
+ (void)initialize
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
semaphore_ = dispatch_semaphore_create(1);
timerDictionary_ = [NSMutableDictionary dictionary];
countDictionary_ = [NSMutableDictionary dictionary];
});
}
+ (NSString *)timerWithInterval:(NSTimeInterval)interval repeatCount:(NSUInteger)count block:(void (^)(NSUInteger remainCount))block;
{
if ((block == nil) || (count <= 0) || (interval <= 0)) return nil;
// gcd定时器基本实现
dispatch_queue_t queue = dispatch_queue_create("com.yusian.timer-queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, interval * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
NSString *timerId = [NSString stringWithFormat:@"%p", timer];
// 字典写入时的线程安全
dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER);
[timerDictionary_ setObject:timer forKey:timerId];
[countDictionary_ setObject:@(count) forKey:timerId];
dispatch_semaphore_signal(semaphore_);
// 执行定时任务
dispatch_source_set_event_handler(timer, ^{
NSNumber *count = [countDictionary_ objectForKey:timerId];
NSUInteger remainCount = count.unsignedIntegerValue;
block(--remainCount);
// 字典写入时的线程安全
dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER);
[countDictionary_ setObject:@(remainCount) forKey:timerId];
dispatch_semaphore_signal(semaphore_);
// 重复次数剩余量为0时自动退出
if (remainCount == 0) [self invalidateWithId:timerId];
});
dispatch_resume(timer);
return timerId;
}
+ (void)invalidateWithId:(NSString *)timerId
{
dispatch_source_t timer = [timerDictionary_ objectForKey:timerId];
if (timer == nil) return;
dispatch_source_cancel(timer);
[timerDictionary_ removeObjectForKey:timerId];
[countDictionary_ removeObjectForKey:timerId];
NSLog(@"SATimer invalidate - %@", timerId);
}
@end