【iOS Tips】009-解析NSTimer

本文详细解析了NSTimer的各种创建方法及其运行原理,并探讨了如何避免强引用导致的内存泄漏问题。此外,还讨论了定时器不准的原因及解决办法,包括在子线程中创建定时器的具体实现。
1、NSTimer方法解析:
//需要加入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相互引用而无法释放。

//在应该销毁Timer的地方调用
- (void)invalidate;
3、定时器不准的问题

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

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

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

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];
});
    

 

 

转载于:https://my.oschina.net/Misayalvyuan/blog/1863936

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值