文档章节

iOS 学习日志 (2) --- NSTimer[转载]

那份牵挂给了谁
 那份牵挂给了谁
发布于 2014/04/19 16:21
字数 1046
阅读 406
收藏 2
点赞 0
评论 0
1. NSRunLoopCommonModes和Timer
    当使用NSTimer的scheduledTimerWithTimeInterval方法时。事实上此时Timer会被加入到当前线程的Run Loop中,且模式是默认的NSDefaultRunLoopMode。而如果当前线程就是主线程,也就是UI线程时,某些UI事件,比如UIScrollView的拖动操作,会将Run Loop切换成NSEventTrackingRunLoopMode模式,在这个过程中,默认的NSDefaultRunLoopMode模式中注册的事件是不会被执行的。也就是说,此时使用scheduledTimerWithTimeInterval添加到Run Loop中的Timer就不会执行。
    所以为了设置一个不被UI干扰的Timer,我们需要手动创建一个Timer,然后使用NSRunLoop的addTimer:forMode:方法来把Timer按照指定模式加入到Run Loop中。这里使用的模式是:NSRunLoopCommonModes,这个模式等效于NSDefaultRunLoopMode和NSEventTrackingRunLoopMode的结合。(参考Apple文档)
参考代码:
- (void)viewDidLoad
{
    [super viewDidLoad];
  NSLog(@"主线程 %@", [NSThread currentThread]);
    //创建Timer
    NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(timer_callback) userInfo:nil repeats:YES];
   注意:将计数器的repeats设置为YES的时候,self的引用计数会加1。因此可能会导致self(即viewController)不能release
    //使用NSRunLoopCommonModes模式,把timer加入到当前Run Loop中。
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}
//timer的回调方法
- (void)timer_callback
{
    NSLog(@"Timer %@", [NSThread currentThread]);
}
输出:
主线程 <NSThread: 0x71501e0>{name = (null), num = 1}
Timer <NSThread: 0x71501e0>{name = (null), num = 1}
Timer <NSThread: 0x71501e0>{name = (null), num = 1}
Timer <NSThread: 0x71501e0>{name = (null), num = 1}
2. NSThread和Timer
    上面讲的NSRunLoopCommonModes和Timer中有一个问题,这个Timer本质上是在当前线程的Run Loop中循环执行的,因此Timer的回调方法不是在另一个线程的。那么怎样在真正的多线程环境下运行一个Timer呢?
    可以先试试NSThread。同上,我们还是会把Timer加到Run Loop中,只不过这个是在另一个线程中,因此我们需要手动执行Run Loop(通过NSRunLoop的run方法),同时注意在新的线程执行中加入@autoreleasepool。
完整代码如下:
- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"主线程 %@", [NSThread currentThread]);
    //创建并执行新的线程
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(newThread) object:nil];
    [thread start];
}
- (void)newThread
{
    @autoreleasepool
    {
        //在当前Run Loop中添加timer,模式是默认的NSDefaultRunLoopMode
        [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(timer_callback) userInfo:nil repeats:YES];
        //开始执行新线程的Run Loop
        [[NSRunLoop currentRunLoop] run];
    }
}
//timer的回调方法
- (void)timer_callback
{
    NSLog(@"Timer %@", [NSThread currentThread]);
}
 输出:
主线程 <NSThread: 0x7118800>{name = (null), num = 1}
Timer <NSThread: 0x715c2e0>{name = (null), num = 3}
Timer <NSThread: 0x715c2e0>{name = (null), num = 3}
Timer <NSThread: 0x715c2e0>{name = (null), num = 3}
3. GCD中的Timer
GCD中的Timer应该是最灵活的,而且是多线程的。GCD中的Timer是靠Dispatch Source来实现的。
因此先需要声明一个dispatch_source_t本地变量:
@interface ViewController ()
{
    dispatch_source_t _timer;
}
接着通过dispatch_source_create函数来创建一个专门的Dispatch Source,接着通过dispatch_source_set_timer函数来设置Timer的参数,注意这里的时间参数有些蛋疼。
开始时间的类型是dispatch_time_t,最好用dispatch_time或者dispatch_walltime函数来创建dispatch_time_t对象。如果需要Timer立即执行,可以传入dispatch_time(DISPATCH_TIME_NOW, 0)。
internal和leeway参数分别表示Timer的间隔时间和精度。类型都是uint64_t。间隔时间的单位竟然是纳秒。可以借助预定义的NSEC_PER_SEC宏,比如如果间隔时间是两秒的话,那interval参数就是:2 * NSEC_PER_SEC。
leeway就是精度参数,代表系统可以延时的时间间隔,最高精度当然就传0。
然后通过dispatch_source_set_event_handler函数来设置Dispatch Source的事件回调,这里当然是使用Block了。
最后所有dispatch_source_t创建后默认都是暂停状态的,所以必须通过dispatch_resume函数来开始事件监听。这里就代表着开始Timer。 
完整代码:
NSLog(@"主线程 %@", [NSThread currentThread]);
//间隔还是2秒
uint64_t interval = 2 * NSEC_PER_SEC;
//创建一个专门执行timer回调的GCD队列
dispatch_queue_t queue = dispatch_queue_create("my queue", 0);
//创建Timer
_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
//使用dispatch_source_set_timer函数设置timer参数
dispatch_source_set_timer(_timer, dispatch_time(DISPATCH_TIME_NOW, 0), interval, 0);
//设置回调
dispatch_source_set_event_handler(_timer, ^()
{
    NSLog(@"Timer %@", [NSThread currentThread]);
});
//dispatch_source默认是Suspended状态,通过dispatch_resume函数开始它
dispatch_resume(_timer);
输出:
主线程 <NSThread: 0x711fab0>{name = (null), num = 1}
Timer <NSThread: 0x713a380>{name = (null), num = 3}
Timer <NSThread: 0x713a380>{name = (null), num = 3}
Timer <NSThread: 0x713a380>{name = (null), num = 3}


本文转载自:http://www.cnblogs.com/mgen/p/3276722.html

共有 人打赏支持
那份牵挂给了谁
粉丝 1
博文 6
码字总数 3727
作品 0
广州
高级程序员
说说 NSTimer 的新 API

本文是我首发在iOS知识小集团队的,欢迎关注微博话题#ios知识小集#。 在以往的 iOS 版本中,我们为了避免 NSTimer 的循环引用问题,一个比较常用的解决办法是为 NSTimer 添加一个 category,...

halohily ⋅ 05/03 ⋅ 0

iOS天气动画、高仿QQ菜单、放京东APP、高仿微信、推送消息等源码

iOS精选源码 TYCyclePagerView iOS上的一个无限循环轮播图组件(http://www.code4app.com/thread-14507-1-1.html) iOS高仿微信完整项目源码(http://www.code4app.com/thread-14695-1-1.html)......

sunnyaigd ⋅ 06/12 ⋅ 0

iOS ZipperDown 漏洞来袭,我们该如何应对?

  昨天傍晚盘古实验室负责任的披露了针对 iOS 应用的 ZipperDown 漏洞,并提供了检索、查询受影响应用的平台: zipperdown.com。基于目前公开的信息,该漏洞的影响面比较大,15000 多个应用...

FreeBuf ⋅ 05/16 ⋅ 0

React Native 【学习总结】-【Jenkins集成】

简述 Jenkins是一个持续集成工具,它本身有很丰富的插件提供使用,方便持续集成,为开发省时省力,下面是项目中对新的RN项目做的持续集成例子,通过该例子学会如何使用jenkins。 Jenkins安装...

Pape ⋅ 05/18 ⋅ 0

如何判断你是合格的高级iOS开发工程师?

前言 随着移动互联网的高速发展泄洪而来,有意学习移动开发的人越来越多了,竞争也是越来越大,需要学习的东西很多。如何才能在激烈的移动开发者竞争中一枝独秀,成为一名真正合格的高级iOS...

_小迷糊 ⋅ 05/26 ⋅ 0

iOS高仿QQ侧滑控件、下载框架、动画效果、扫一扫、颜色变化、K线图等源码

iOS精选源码 仿京东"加入购物车"转场动画(http://www.code4app.com/thread-28162-1-1.html) ColorTool(颜色转换)(http://www.code4app.com/thread-29256-1-1.html) Swift 专业版K线(http://w......

sunnyaigd ⋅ 04/17 ⋅ 0

ZipperDown漏洞来了!微博、陌陌、快手等常用 iOS 应用恐要中招

雷锋网(公众号:雷锋网)消息,5月15日,盘古实验室对外宣布,他们在针对不同客户的 iOS 应用安全审计过程中,发现了一类通用的安全漏洞---ZipperDown漏洞。 10%的iOS应用可能受ZipperDow...

郭佳 ⋅ 05/15 ⋅ 0

2018 一份"有点难"的iOS面试题(5年iOS开发)

序言: 之前一时兴致在本站上出过一份iOS的中级面试题,引起一些关注,不少同学表示对”隐藏关卡“感兴趣。升级版iOS面试题来了,目测难倒90%iOS程序员,目测一大波程序员撸着袖子在靠近。 ...

原来是泽镜啊 ⋅ 05/26 ⋅ 0

一样的iOS开发程序员为什么有人4k有人40k?

前言 移动开发真正火起来其实就是最近这几年,iOS 开发技术因为发展也就才这么几年,所以值得做的事情还有很多,这就造成了每年苹果的 WWDC 都会推出一堆新的特性和 API。整体上来说,这对业...

原来是泽镜啊 ⋅ 05/16 ⋅ 0

iOS12 beta 1系统被攻破,越狱视频被分享

半个月前,iOS 12 在 WWDC 2018 苹果全球开发者大会上正式亮相,开发者用户开始下载iOS 12 开发者预览版 Beta1 固件进行升级体验。 十几天后,6月17日凌晨2点,腾讯科恩团队在推特分享了iOS...

又田 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

聊聊spring cloud gateway的LoadBalancerClientFilter

序 本文主要研究一下spring cloud gateway的LoadBalancerClientFilter GatewayLoadBalancerClientAutoConfiguration spring-cloud-gateway-core-2.0.0.RELEASE-sources.jar!/org/springfram......

go4it ⋅ 29分钟前 ⋅ 0

详解:Nginx反代实现Kibana登录认证功能

Kibana 5.5 版后,已不支持认证功能,也就是说,直接打开页面就能管理,想想都不安全,不过官方提供了 X-Pack 认证,但有时间限制。毕竟X-Pack是商业版。 下面我将操作如何使用Nginx反向代理...

问题终结者 ⋅ 35分钟前 ⋅ 0

002、nginx配置虚拟主机

一、nginx配置虚拟主机可分为三种方式,分别为: 1、基于域名的虚拟主机,通过域名来区分虚拟主机——应用:外部网站 2、基于端口的虚拟主机,通过端口来区分虚拟主机——应用:公司内部网站...

北岩 ⋅ 38分钟前 ⋅ 0

shell脚本之死循环写法

最近在学习写shell脚本,在练习if while等流程控制时,突然它们的死循环写法是怎么样的?经过百度与亲测记录如下: for死循环 #! /bin/bashfor ((;;));do date sleep 1d...

hensemlee ⋅ 41分钟前 ⋅ 0

苹果的ARKit2.0有多可怕,看了就知道

序言 ARKit主要由三部分组成: 跟踪(Tracking) 跟踪是ARKit的核心组件之一,其提供了设备在物理世界中的位置与方向信息,并对物体进行跟踪,如人脸。 2.场景理解(Scene Understanding) 场...

_小迷糊 ⋅ 41分钟前 ⋅ 0

5.1 vim介绍 5.2 vim移动光标 5.3 ,5.4vim一般模式下移动光标,复制粘贴

vim命令 vim是vi的一个升级版;vim可以显示文字的颜色 安装vim这一个包vim-enhanced 如果不知道安装包,可以使用 命令下面命令来查看vim命令是那个包安装的。 [root@linux-128 ~]# yum prov...

Linux_老吴 ⋅ 45分钟前 ⋅ 0

vim一般模式

vim 是什么 vim是什么 ? 在之前接触Linux,编辑网卡配置文件的时候我们用过了vi ,vim简单说就是vi的升级版,它跟vi一样是Linux系统中的一个文本编辑工具。 如果系统中没有vim ,需要安装一...

李超小牛子 ⋅ 53分钟前 ⋅ 0

docker实战

构建企业级Docker虚拟化平台实战 重点剖析虚拟化和云计算概念; 分析Docker虚拟化的概念和原理; 从0开始实战Docker虚拟化平台; 基于Docker构建Nginx WEB服务器和CentOS虚拟机; 基于开源监...

寰宇01 ⋅ 今天 ⋅ 0

vim介绍、vim颜色显示和移动光标、vim一般模式下移动光标、一般模式下复制粘贴剪切

VIM Vim 是 UNIX 文本编辑器 Vi 的加强版本,加入了更多特性来帮助编辑源代码。Vim 的部分增强功能包括文件比较(vimdiff),语法高亮,全面的帮助系统,本地脚本(Vimscript),和便于选择的...

蛋黄Yolks ⋅ 今天 ⋅ 0

springboot+mockito测试controller层遇到的问题

使用MockitoJUnitRunner测试的一个例子,原来报错无法找到bean, 类似的异常如下:createBeanError..... 原因:是因为@Runwith使用了SpringRunner,应该修改为MockitoJUnitRunner 代码如下: ...

writeademo ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部