定时器
·2 分钟
OC
NSTimer
目录
Objc - 系列文章之一
Part 17: 当前阅读
NSTimer、CADisplayLink定时器>
NSTimer、CADisplayLink定时器 #
CADisplayLink使用
@interface TMViewController ()
@property (strong, nonatomic) CADisplayLink * link;
@end
- (void)viewDidLoad {
[super viewDidLoad];
_link = [CADisplayLink displayLinkWithTarget:(id)target selector:@selector(linkTest)];
[_link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}
- (void)dealloc {
[_link invalidate];
}
NSTimer使用
@interface TMViewController ()
@property (strong, nonatomic) NSTimer * timer;
@end
- (void)viewDidLoad {
[super viewDidLoad];
_timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:(id)target selector:@selector(linkTest) userInfo:nil repeats:YES];
}
- (void)dealloc {
[_timer invalidate];
}
以上方式如果将target
传为self
,则会造成self
对timer
的强引用,timer
又对self
强引用,双方释放不了,造成循环引用
。
解决方法>
解决方法 #
- 创建一个不依赖于
self
的timer
- (void)viewDidLoad {
[super viewDidLoad];
_timer = [NSTimer timerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
NSLog(@"执行任务");
}];
[[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode];
}
- (void)dealloc {
[_timer invalidate];
}
- 添加中间对象(NSProxy),弱引用
self
然后将消息转发给self
。
- (void)viewDidLoad {
[super viewDidLoad];
_timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:[TMProxy initWithTarget:self] selector:@selector(linkTest) userInfo:nil repeats:YES];
}
- (void)dealloc {
[_timer invalidate];
}
// TMProxy实现
@interface TMProxy ()
@property (weak, nonatomic) id target;
@end
@implementation TMProxy
+ (TMProxy *)initWithTarget:(id)target {
TMProxy *proxy = [TMProxy alloc];
proxy.target = target;
return proxy;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
return [_target methodSignatureForSelector:sel];
}
- (void)forwardInvocation:(NSInvocation *)invocation {
[invocation invokeWithTarget:_target];
}
@end
GCD定时器>
GCD定时器 #
由于NSTimer
是依赖于RunLoop
进行工作的,而RunLoop
内部除了需要执行NSTimer
事务,同时也可能处理其他事务,所以RunLoop
进行计时会又不准确的情况。而GCD
不依赖于RunLoop
,GCD定时器
属于系统层面。所以GCD定时器
能够相对准确。
创建GCD定时器>
创建GCD定时器 #
@interface ViewController ()
@property (strong, nonatomic) dispatch_source_t timer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC, 0);
dispatch_source_set_event_handler(timer, ^{
NSLog(@"gcd timer counting.");
});
dispatch_resume(timer);
// 防止timer被释放。
_timer = timer;
}
@end
Objc - 系列文章之一
Part 17: 当前阅读