自定义计时器,通过dispatch_after()实现

1、设计思路

1.1、系统类NSTimer做一次性计时使用还可以,如果需要暂停继续的话就不太灵活了;
1.2、通过dispatch_after延时执行函数,配套循环语句算法实现间隔n秒触发一次调用;
1.3、设计一个状态属性,对当前的状态进行管理,如准备、暂停、继续、开始、结束等;

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//
//  SATimer.h
//  Test
//
//  Created by 余西安 on 16/8/11.
//  Copyright ? 2016年 Sian. All rights reserved.
//
 
#import <foundation /Foundation.h>
// 定时器状态
typedef NS_ENUM(NSInteger, SATimerStatus){
    SATimerStatusReady = 0, // 准备
    SATimerStatusRunning,   // 正在运行
    SATimerStatusPaused,    // 已暂停,可继续计时
    SATimerStatusStoped     // 已停止,只能重新开始
};
 
typedef void (^SATimerBlock)(NSUInteger remainCount);
 
@interface SATimer : NSObject
// 间隔时间
@property (nonatomic, assign) NSTimeInterval interval;
// 重复次数
@property (nonatomic, assign) NSUInteger     repeatCount;
 
@property (nonatomic, assign) SATimerStatus  status;
 
+ (instancetype)timeWithInterval:(NSTimeInterval)ti repeatCount:(NSInteger)count block:(SATimerBlock)block;
 
- (instancetype)initWithInterval:(NSTimeInterval)ti repeatCount:(NSInteger)count block:(SATimerBlock)block;
// 开始(重新开始)
- (void)start;
// 暂停(可继续)
- (void)pause;
// 继续
- (void)continues;
// 停止(不可继续,只能重新开始)
- (void)stop;
 
@end
</foundation>

3、实现

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
56
57
58
59
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
85
86
87
88
89
90
//
//  SATimer.m
//  Test
//
//  Created by 余西安 on 16/8/11.
//  Copyright ? 2016年 Sian. All rights reserved.
//
 
#import "SATimer.h"
 
@interface SATimer ()
 
@property (nonatomic, assign) NSInteger  currentCount;
 
@property (nonatomic, copy) SATimerBlock block;
 
@end
 
@implementation SATimer
 
+ (instancetype)timeWithInterval:(NSTimeInterval)ti repeatCount:(NSInteger)count block:(SATimerBlock)block
{
    return [[self alloc] initWithInterval:ti repeatCount:count block:block];
}
 
- (instancetype)initWithInterval:(NSTimeInterval)ti repeatCount:(NSInteger)count block:(SATimerBlock)block
{
    if (self = [super init]){
        self.interval = ti;
        self.repeatCount = count;
        self.currentCount = count;
        self.block = block;
    }
    return self;
}
 
- (void)repeatMethod
{
 
    if (self.currentCount <= 0 || self.status != SATimerStatusRunning) return;
    self.currentCount--;
    if (self.block) self.block(self.currentCount);
 
    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (self.interval * NSEC_PER_SEC));
    dispatch_after(time, dispatch_get_main_queue(), ^{
 
 
        [self repeatMethod];
    });
 
}
 
- (void)start
{
    if (self.status == SATimerStatusRunning) return;
    self.currentCount = self.repeatCount;
    self.status = SATimerStatusRunning;
    [self repeatMethod];
}
 
- (void)continues
{
    if (self.status == SATimerStatusRunning || self.currentCount == 0) return;
    self.status = SATimerStatusRunning;
    [self repeatMethod];
}
 
- (void)pause
{
    self.status = SATimerStatusPaused;
}
 
- (void)stop
{
    self.status = SATimerStatusStoped;
    self.currentCount = 0;
}
 
- (void)setCurrentCount:(NSInteger)currentCount
{
    self->_currentCount = currentCount;
    if (currentCount == 0) self.status = SATimerStatusStoped;
}
 
- (void)dealloc
{
    NSLog(@"%@---dealloc", self);
}
 
@end

Leave a Reply