NSTimer介绍

news/2024/7/20 22:12:03 标签: objective-c, xcode, ios

1.创建NSTimer

常用方法有

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

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

- (instancetype)initWithFireDate:(NSDate *)date interval:(NSTimeInterval)ti target:(id)target selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)repeats;

他们的区别:

scheduledTimerWithTimeInterval相比它的小伙伴们不仅仅是创建了NSTimer对象, 还把该对象加入到了当前的runloop中!

NSTimer只有被加入到runloop, 才会生效, 即NSTimer才会被真正执行

所以说, 如果你想使用timerWithTimeInterval或initWithFireDate的话, 需要使用NSRunloop的以下方法将NSTimer加入到runloop中

- (void)addTimer:(NSTimer *)aTimer forMode:(NSString *)mode

要让timer生效,必须保证该线程的runloop已启动,而且其运行的runloopmode也要匹配。

每一个线程都有它自己的runloop,程序的主线程会自动的使runloop生效,

但对于我们自己新建的线程,它的runloop是不会自己运行起来,当我们需要使用它的runloop时,就得自己启动。

runloop会运行在不同的mode, 简单来说有以下两种mode

NSDefaultRunLoopMode, 默认的mode

UITrackingRunLoopMode, 当处理UI滚动操作时的mode

主线程默认运行在NSDefaultRunLoopMode

在UI滚动时, runloop运行在UITrackingRunLoopMode

如果addTimerforMode是NSDefaultRunLoopMode,那么在UITrackingRunLoopMode下定时器就不运行

要想在这些场景下仍然及时触发NSTimer那应该怎么办呢?

应该使用NSRunLoopCommonModes,包含以上2个mode

[[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];

例子

//创建一个定时器,

_timer=[NSTimer timerWithTimeInterval:10 target:self selector:@selector(changeTimeAtTimedisplay) userInfo:nil repeats:YES];



//手动加入到循环中

NSRunLoop *runloop=[NSRunLoop currentRunLoop];

[runloop addTimer:_timer forMode:NSRunLoopCommonModes];

当然这个定时器会自动启动,只不多过了十秒之后,才触发

fire的作用是提前触发定时器 ,如果执行

_timer.fireDate = CFAbsoluteTimeGetCurrent() + timeInterval;

那么会立即开始定时

2.销毁NSTimer

是否可以将NSTimer置nil, 而让iOS系统帮我们销毁NSTimer呢?

答案是: 不可以

原因:为了保证timer在未来触发指定事件时指定方法是有效的,将指定方法的接收者retain了一份。(重复性还是一次性的timer都是)

如果在VC在创建的NSTimer,VC会和timer相互强引用,VC的dealloc方法不会执行

[_timer invalidate]; // 可以打破相互强引用,真正销毁NSTimer对象

_timer = nil; // 对象置nil是一种规范和习惯

所以这段代码不能放在VC的dealloc方法中,可以放在VC的ViewWillDisappear方法中

3.NSTimer会是准时触发事件吗

答案是否定的。

NSTimer不是一个实时系统,因此不管是一次性的还是周期性的timer的实际触发事件的时间可能都会跟我们预想的会有出入。差距的大小跟当前我们程序的执行情况有关系,比如可能程序是多线程的,而你的timer只是添加在某一个线程的runloop的某一种指定的runloopmode中,由于多线程通常都是分时执行的,而且每次执行的mode也可能随着实际情况发生变化。

  假设你添加了一个timer指定2秒后触发某一个事件,但是签好那个时候当前线程在执行一个连续运算(例如大数据块的处理等),这个时候timer就会延迟到该连续运算执行完以后才会执行。重复性的timer遇到这种情况,如果延迟超过了一个周期,则会和后面的触发进行合并,即在一个周期内只会触发一次。但是不管该timer的触发时间延迟的有多离谱,他后面的timer的触发时间总是倍数于第一次添加timer的间隙。

4.BlocksKit中为NSTimer 写的分类

@implementation NSTimer (BlocksKit)

+ (instancetype)bk_scheduleTimerWithTimeInterval:(NSTimeInterval)seconds repeats:(BOOL)repeats usingBlock:(void (^)(NSTimer *timer))block

{

    NSTimer *timer = [self bk_timerWithTimeInterval:seconds repeats:repeats usingBlock:block];

    [NSRunLoop.currentRunLoop addTimer:timer forMode:NSDefaultRunLoopMode];

    return timer;

}

+ (instancetype)bk_timerWithTimeInterval:(NSTimeInterval)inSeconds repeats:(BOOL)repeats usingBlock:(void (^)(NSTimer *timer))block

{

    NSParameterAssert(block != nil);

    CFAbsoluteTime seconds = fmax(inSeconds, 0.0001);

    CFAbsoluteTime interval = repeats ? seconds : 0;

    CFAbsoluteTime fireDate = CFAbsoluteTimeGetCurrent() + seconds;

    return (__bridge_transfer NSTimer *)CFRunLoopTimerCreateWithHandler(NULL, fireDate, interval, 0, 0, (void(^)(CFRunLoopTimerRef))block);

}


http://www.niftyadmin.cn/n/905312.html

相关文章

纪念12月21,展望2019

2015年12月21日,第一家公司入职; 2018年12月21日,第二家公司转正; 回顾三年有太多的不如意与不甘,愿在来年的2019可以坚定决心,坚定不移的一直走下去,为了让自己和家人生活的更好,以…

iOS保存图片到相册

方法1:用C语言函数UIImageWriteToSavedPhotosAlbum实现 //参数1:图片对象 //参数2:成功方法绑定的target //参数3:成功后调用方法 //参数4:需要传递信息(成功后调用方法的参数) UIImageWriteToSavedPhotosAlbum(self.imageView.image, self, selector(image:didFin…

计算机视觉与遥感实验室(CVRS Lab)

http://cvrs.whu.edu.cn/ 武汉大学计算机视觉与遥感实验室(WHU-CVRS Lab)由学校高层次引进人才姚剑教授于2012年4月创建成立,目前成员包括1名博士后,20余名博士和硕士研究生,10多名本科生。自从成立至今,CV…

2018-12-25工作记录 空白行===水晶报表

C# 多行文本去掉空白行,空行和重复行 string[] strArraystr.Split(new char[] { \r, \n }, StringSplitOptions.RemoveEmptyEntries); strArray strArray.GroupBy(p > p).Select(p > p.Key).ToArray(); 水晶报表:一般先建立一个数据集&#xff0c…

iOS 显示圆角、阴影和边框

iOS 同时显示圆角(部分)、阴影和边框 在 iOS 开发中,让View显示圆角和阴影以及边框 方法1:系统的UIView UIView *v[[UIView alloc]initWithFrame:CGRectMake(100, 200, viewWidth, viewHeight)];v.backgroundColor[UIColor yellowColor]; // v.layer.m…

Windows上提高工作效率的神器推荐

Everything 下载地址:http://www.voidtools.com/功能:硬盘文件搜索,比起电脑自带的文件搜索,效率提高不是一丁半点。而且Everything还支持正则表达式,小巧而快速;Clover 下载地址:http://cn.eji…

keychain介绍

1. keychain概述 1.1 keychain是什么 苹果官网对钥匙串的描述 iOS keychain 是一个相对独立的空间,是用SQLite进行存储的,可以加密我们保存的数据,并且使用keychain service API增删改查。 keychain的是以item为单位存储的。data是数据本身…

@codeforces - 786E@ ALT

目录 description - translationsolutionpart - 1part - 2part - 3accepted codedetailsdescription - translation 给定一棵含 n 个点的树和 m 个人,第 i 个人会从结点 xi 走到 结点 yi。 每个人有一个需求:要么他开局自带一条狗,要么他走的…