NSTimer宙攻、CADisplayLink依賴Runloop,如果Runloop的任務(wù)過(guò)于繁重介褥,可能導(dǎo)致NSTimer不準(zhǔn)時(shí)座掘。
GCD的定時(shí)器dispatch_source_t更準(zhǔn)時(shí),不依賴Runloop柔滔。
NSTimer:
@property (nonatomic, strong) NSTimer *timer;
#pragma mark 創(chuàng)建定時(shí)器
- (void)initTimer0 {
//創(chuàng)建定時(shí)器1
self.timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(updateTimer) userInfo:nil repeats:YES];
//創(chuàng)建定時(shí)器2
self.timer = [NSTimer timerWithTimeInterval:2 target:self selector:@selector(updateTimer) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode];
}
#pragma mark 解決循環(huán)引用1
- (void)initTimer1 {
__weak typeof(self) weakSelf = self;
//self強(qiáng)引用timer溢陪,timer強(qiáng)引用block,block弱引用self,進(jìn)而timer弱引用self,打破循環(huán)引用
self.timer = [NSTimer scheduledTimerWithTimeInterval:2 repeats:YES block:^(NSTimer * _Nonnull timer) {
[weakSelf updateTimer];
}];
}
#pragma mark 解決循環(huán)引用2
- (void)initTimer {
//創(chuàng)建中間對(duì)象
self.timer = [NSTimer scheduledTimerWithTimeInterval:2 target:[TimerProxy initWithTarget:self] selector:@selector(updateTimer) userInfo:nil repeats:YES];
}
- (void)updateTimer {
NSLog(@"%s", __func__);
}
- (void)dealloc
{
NSLog(@"%s", __func__);
[self.timer invalidate];
}
CADisplayLink:
@property (nonatomic, strong) CADisplayLink *link;
- (void)initLink {
//保證調(diào)用頻率和屏幕的刷新幀率一致睛廊,60fps
self.link = [CADisplayLink displayLinkWithTarget:[TimerProxy1 initWithTarget:self] selector:@selector(updateTimer)];
//添加到runloop
[self.link addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
- (void)updateTimer {
NSLog(@"%s", __func__);
}
- (void)dealloc
{
NSLog(@"%s", __func__);
[self.link invalidate];
}
NSProxy形真、NSObject都是基類。
NSProxy專門(mén)做代理的超全,在找不到方法時(shí)没酣,不會(huì)從類、父類進(jìn)行方法的查找卵迂,直接進(jìn)行方法簽名和方法調(diào)用裕便。效率更高。
NSObject會(huì)在找不到方法時(shí)见咒,進(jìn)行消息查找偿衰、消息轉(zhuǎn)發(fā)。
創(chuàng)建中間對(duì)象TimerProxy繼承NSObject:
@interface TimerProxy : NSObject
//弱引用對(duì)象
@property (nonatomic, weak) id target;
+ (instancetype)initWithTarget:(id)target;
@end
@implementation TimerProxy
+ (instancetype)initWithTarget:(id)target {
TimerProxy *proxy = [[TimerProxy alloc] init];
proxy.target = target;
return proxy;
}
#pragma mark 消息轉(zhuǎn)發(fā)
- (id)forwardingTargetForSelector:(SEL)aSelector {
return self.target;
}
@end
創(chuàng)建中間對(duì)象TimerProxy1繼承NSProxy:
@interface TimerProxy1 : NSProxy
@property (nonatomic, weak) id target;
+ (instancetype)initWithTarget:(id)target;
@end
+ (instancetype)initWithTarget:(id)target {
//NSProxy沒(méi)有init方法
TimerProxy1 *proxy = [TimerProxy1 alloc];
proxy.target = target;
return proxy;
}
#pragma mark 方法簽名
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
return [self.target methodSignatureForSelector:sel];
}
#pragma mark 方法調(diào)用
- (void)forwardInvocation:(NSInvocation *)invocation {
[invocation invokeWithTarget:self.target];
}
創(chuàng)建GCD定時(shí)器:dispatch_source_t改览,不依賴Runloop
@property (nonatomic, strong) dispatch_source_t timer;
#pragma mark 創(chuàng)建GCD定時(shí)器
- (void)initGCDTimer {
NSLog(@"begin");
// dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_queue_t queue = dispatch_queue_create("myqueue", DISPATCH_QUEUE_SERIAL);
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
//設(shè)置事件處理
dispatch_source_set_event_handler(self.timer, ^{
NSLog(@"處理定時(shí)器任務(wù)%@", [NSThread currentThread]);
});
uint64_t start = 1;
uint64_t interval = 2;
dispatch_source_set_timer(self.timer, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(start * NSEC_PER_SEC)), (uint64_t)(interval * NSEC_PER_SEC), 0);
//啟動(dòng)定時(shí)器
dispatch_resume(self.timer);
}