惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

大猫的无限游戏
大猫的无限游戏
博客园 - 【当耐特】
Cloudbric
Cloudbric
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Attack and Defense Labs
Attack and Defense Labs
爱范儿
爱范儿
The Cloudflare Blog
腾讯CDC
Security Archives - TechRepublic
Security Archives - TechRepublic
TaoSecurity Blog
TaoSecurity Blog
云风的 BLOG
云风的 BLOG
Recent Announcements
Recent Announcements
C
Check Point Blog
Schneier on Security
Schneier on Security
S
Schneier on Security
J
Java Code Geeks
B
Blog RSS Feed
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
Stack Overflow Blog
Stack Overflow Blog
博客园_首页
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
A
About on SuperTechFans
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Google DeepMind News
Google DeepMind News
阮一峰的网络日志
阮一峰的网络日志
罗磊的独立博客
A
Arctic Wolf
S
Secure Thoughts
P
Palo Alto Networks Blog
The Last Watchdog
The Last Watchdog
SecWiki News
SecWiki News
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
博客园 - 三生石上(FineUI控件)
D
Darknet – Hacking Tools, Hacker News & Cyber Security
量子位
U
Unit 42
I
InfoQ
D
DataBreaches.Net
P
Privacy International News Feed
T
Troy Hunt's Blog
博客园 - 叶小钗
T
Threatpost
博客园 - Franky
K
Kaspersky official blog
Hugging Face - Blog
Hugging Face - Blog
IT之家
IT之家
www.infosecurity-magazine.com
www.infosecurity-magazine.com
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
C
Cisco Blogs

博客园 - zhoup

文鹏教育_jmeter培训_逻辑控制器_循环取样器 02 jmeter性能测试系列_JForum测试论坛的环境搭建 01 jmeter性能测试系列_Jmeter的体系结构 实战p12文件转pem文件 UIViewContentMode各类型效果 给iOS开发新手送点福利,简述文本属性Attributes的用法 IOS 设置导航栏全局样式 iOS 在tableView上添加button导致按钮没有点击效果和不能滑动的 zhuang xcode 插件地址 AFNnetworking详解 NSRunLoop详解 利用SQL注入漏洞登录后台的实现方法 Xcode 7免证书真机调试 [转]CABasicAnimation用法 zhuang 定制iOS 7中的导航栏和状态栏 zhuang 自定义Xcode代码模板:Code Snippet [zhang] ViewController的生命周期分析和使用 iOS开发--一些UITabBarItem属性的设置[转] UINavigationItem UINavigationBar 关系分析[转]
NSTimer的使用[zhuang]
zhoup · 2016-04-21 · via 博客园 - zhoup

NSTimer 的头文件

/*    NSTimer.h
    Copyright (c) 1994-2015, Apple Inc. All rights reserved.
*/

#import <Foundation/NSObject.h>
#import <Foundation/NSDate.h>

NS_ASSUME_NONNULL_BEGIN

@interface NSTimer : NSObject

注意:这五种初始化方法的异同:

    1、参数repeats是指定是否循环执行,YES将循环,NO将只执行一次。
    2、timerWithTimeInterval  这两个类方法创建出来的对象如果不用 addTimer: forMode方法手动加入主循环池中,将不会循环执行。
    3、scheduledTimerWithTimeInterval  这两个方法会将定时器添加到当前的运行循环,运行循环的模式为默认模式。
    4、init方法需要手动加入循环池,它会在设定的启动时间启动。

NSTimer 使用过程中的问题:
1、 内存释放问题
如果我们启动了一个定时器,在某个界面释放前,将这个定时器停止,甚至置为nil,都不能使这个界面释放,原因是系统的循环池中还保有这个对象。
timer都会对它的target进行retain,我们需要小心对待这个target的生命周期问题,尤其是重复性的timer

所以我们需要这样做:

-(void)dealloc{
       NSLog(@"dealloc:%@",[self class]);
}

- (void)viewDidLoad {
      [super viewDidLoad];
      timer= [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(myLog:) userInfo:nil repeats:YES];
UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
      btn.backgroundColor=[UIColor redColor];
      [btn addTarget:self action:@selector(btn) forControlEvents:UIControlEventTouchUpInside];
      [self.view addSubview:btn];
}

-(void)btn{    
      if (timer.isValid) {       
          [timer invalidate];  

NSTimer为什么要添加到RunLoop中才会有作用

便利构造器,它其实是做了两件事:
首先创建一个timer,然后将该timer添加到当前runloop的default mode中。

也就是这个便利方法给我们造成了只要创建了timer就可以生效的错觉,我们当然可以自己创建timer,然后手动的把它添加到指定runloop的指定mode中去。

NSTimer其实也是一种资源(事件),如果看过多线程变成指引文档的话,我们会发现所有的source(事件)如果要起作用,就得加到runloop中去。
同理timer这种资源要想起作用,那肯定也需要加到runloop中才会有效喽。
如果一个runloop里面不包含任何资源(事件)的话,运行该runloop时会处于一种休眠状态等待下一个事件。

没有将事件添加到运行循环中

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    [self testTimerWithOutShedule];
}

- (void)testTimerWithOutShedule
{
    NSLog(@"Test timer without shedult to runloop");
    SvTestObject *testObject3 = [[SvTestObject alloc] init];
    NSTimer *timer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:1] interval:1 target:testObject3 selector:@selector(timerAction:) userInfo:nil repeats:NO];

    NSLog(@"invoke release to testObject3");
}

- (void)applicationWillResignActive:(UIApplication *)application
{
    NSLog(@"SvTimerSample Will resign Avtive!");
}

我们新建了一个timer,为它指定了有效的target和selector,并指出了1秒后触发该消息,运行结果如下:

Snip20151212_4.png

消息永远也不会触发,原因很简单,我们没有将timer添加到runloop中。
  综上: 必须得把timer添加到runloop中,它才会生效。

NSTimer加到了RunLoop中但迟迟的不触发事件

原因主要有以下两个:
1、runloop是否运行
每一个线程都有它自己的runloop,程序的主线程会自动的使runloop生效,但对于我们自己新建的线程,它的runloop是不会自己运行起来,当我们需要使用它的runloop时,就得自己启动。

- (void)applicationDidBecomeActive:(UIApplication *)application
{
     // NSThread 创建一个子线程
    [NSThread  detachNewThreadSelector:@selector(testTimerSheduleToRunloop1) toTarget:self withObject:nil];
}

我们新创建了一个线程,然后创建一个timer,并把它添加当该线程的runloop当中,但是运行结果如下:

Snip20151212_5.png

发现这个timer知道执行退出也没有触发我们指定的方法,如果我们把上面测试程序中“

//[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:3]];

这一行的注释去掉,则timer将会正确的掉用我们指定的方法。

2、mode是否正确
手动添加runloop的时候,可以看到有一个参数runloopMode,这个参数是干嘛的呢?
  前面提到了要想timer生效,我们就得把它添加到指定runloop的指定mode中去,通常是主线程的defalut mode。但有时我们这样做了,却仍然发现timer还是没有触发事件。
这是因为timer添加的时候,我们需要指定一个mode,因为同一线程的runloop在运行的时候,任意时刻只能处于一种mode。所以只能当程序处于这种mode的时候,timer才能得到触发事件的机会。

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

//不重复,只调用一次。timer运行一次就会自动停止运行 
myTimer = [NSTimer scheduledTimerWithTimeInterval:1.5 target:self selector:@selector(scrollTimer) userInfo:nil repeats:NO];  


需要重复调用, repeats参数改为 YES . ---> 定时器的模式是默认的

注意点:
[timer invalidate]是唯一的方法将定时器从循环池中移除
NSTimer可以精确到50-100毫秒.
NSTimeInterval类:是一个浮点数字,用来定义秒
NSTimer不是绝对准确的,而且中间耗时或阻塞错过下一个点,那么下一个点就pass过去了.

文/潇小溅(简书作者)
原文链接:http://www.jianshu.com/p/3ccdda0679c1
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。