Home 009-解析NSTimer
Post
Cancel

009-解析NSTimer

1、NSTimer方法解析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//需要加入runloop 需要调用fire启动

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo; 

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

//需要加入runloop 
- (instancetype)initWithFireDate:(NSDate *)date interval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

- (instancetype)initWithFireDate:(NSDate *)date interval:(NSTimeInterval)ti target:(id)t selector:(SEL)s userInfo:(nullable id)ui repeats:(BOOL)rep NS_DESIGNATED_INITIALIZER;

//会默认加入mainRunLoop中 直接启动
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;


+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;


+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));


通过试验发现:通过-(id)init 和 +(id)timer 方法创建的timer都需要手动加到runloop中才可以执行;通过+(id)scheduledTimer方法创建的timer会自动加入mainRunloop中,并且可以直接执行。

2、关于强引用问题。

通常我们在某个类中使用taget-selector或block去执行的时候,timer会对其强引用。比如在一个视图控制器,当我们使用target-selector时,通常需要在dealloc时调用下面这个方法。当使用block时,还要在代码块中应使用weakSelf。以防止试图控制器和timer相互引用而无法释放。

1
2
3
//在应该销毁Timer的地方调用
- (void)invalidate;

3、定时器不准的问题

首先,NSDefaultRunLoopMode 模式中,程序会优先处理输入源事件,处理输入源事件时,不能处理定时源事件

还有,通常我们都会在主线程创建定时器,但是当主线程阻塞时,定时器也会被阻塞,这样就会造成定时器掉帧、不准。

解决方法:在子线程中创建定时器,如下所示:

1
2
3
4
5
6
7
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSTimer *timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(timer1Action) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop]addTimer:timer forMode:NSRunLoopCommonModes];
        [timer fire];
        [[NSRunLoop currentRunLoop]run];
});
    
This post is licensed under CC BY 4.0 by the author.

004-继承、类别、扩展含义及区别?

Flutter版本管理之FVM深入解析