zoukankan      html  css  js  c++  java
  • NSTimer简介

    NSTimer顾名思义是定时器,在IOS开发中可以用于设定一定的时间间隔,让其执行一段代码,常用于小游戏中的计时功能或者倒计时功能实现。

    一、 初始化定时器(常用的2种):

    //(1)
    + (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;//(常用)
    //(2)
    + (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;//(常用)

    两种初始化方法的区别:
    1、timerWithTimeInterval这个类方法(1)创建出来的对象如果不用 addTimer: forMode方法手动加入主循环池中,将不会循环执行。并且如果不手动调用fair,则定时器不会启动。
    2、scheduledTimerWithTimeInterval这个方法(2)不需要手动调用fair,会自动执行,并且自动加入主循环池。
    代码:

    /** 参数介绍
    *   timerWithTimeInterval: 表示输入一个时间间隔对象,以秒为单位,一个>0的浮点类型的值,如果该值<0,系统会默认为0.1
    *   target: 事件代理,一般填self
    *   selector: 方法选择器,在时间间隔内,选择调用一个实例方法
    *   userInfo: timer携带的信息(可以有timer1.userInfo取出)
    *   repeats:是否循环 (YES-循环执行; NO-执行一次停止)
    *   注意:当YES时,定时器会不断循环直至失效或被释放,当NO时,定时器会循环发送一次就失效。
    */
    //初始化定时器timer1
    NSTimer *timer1 = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(myFun:) userInfo:nil repeats:YES];
    //将定时器timer1加入主循环池中
    [[NSRunLoop mainRunLoop]addTimer:timer1 forMode:NSDefaultRunLoopMode];
    //开始循环定时器timer1
    [timer1 fire];
    
    //初始化定时器timer2,并开始循环
    NSTimer *timer2 = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(myFun:) userInfo:@"abc" repeats:YES]

    注意:将计数器的repeats设置为YES的时候,self的引用计数会加1。因此可能会导致self(即viewController)不能release,所以,必须在合适的时间或者viewWillAppear的时候,将计数器timer停止,否则可能会导致内存泄露。

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

    还有一种情况是,将NSTimer添加进主运行循环,当主线程有较多的任务的时候(比如有较多的UI操作),那么主线程可能就会阻塞NSTimer,进而执行UI操作。
    这类的解决办法是:将定时器用NSRunLoopCommonModes模式添加到主运行循环中。

    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(myLog:) userInfo:nil repeats:YES];
    //将其添加到主运行循环,防止阻塞
    [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

    三 关于内存释放

    @property (nonatomic, strong) NSTimer timer;
    
    -(void)dealloc{
        NSLog(@"dealloc");
    }
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        //初始化定时器
        self.timer= [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(myLog:) userInfo:nil repeats:YES];
    
        //添加一个返回按钮
        UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 50, 50)];
        btn.backgroundColor=[UIColor blueColor];
        [btn addTarget:self action:@selector(btnClick) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:btn];
    }
    
    //监听按钮点击
    -(void)btnClick{
    //(要在控制器销毁之前将定时器移除,并清空),这样才能避免循环引用,防止内存泄露
        if ([self.timer isValid]) {
            [self.timer invalidate];
        }
        self.timer=nil;
        [self dismissViewControllerAnimated:YES completion:nil];
    }

    四 分类
    在使用定时器的时候,可以给定时器创建一个分类,方便调用

    #import <Foundation/Foundation.h>
    @interface NSTimer (Extension)
    /** 暂停定时器 */
    - (void)pauseTimer;
    /** 重启定时器 */
    - (void)resumeTimer;
    /** 销毁定时器 */
    - (void)removeTimer;
    @end
    
    
    @implementation NSTimer (Extension)
    /** 暂停定时器 */
    -(void)pauseTimer{
        if (![self isValid]) return ;
        [self setFireDate:[NSDate distantFuture]];
    }
    
    /** 重启定时器 */
    -(void)resumeTimer{
        if (![self isValid]) return;
        [self setFireDate:[NSDate date]];
    }
    
    /** 销毁定时器 */
    - (void)removeTimer{
        if (![self isValid]) return;
        [self invalidate];
        self = nil;
    }
    @end

    总结:在使用定时器的时候,需要注意的就是内存释放的问题,关键是在合适的地方销毁定时器,防止其与控制器循环引用。还有就是 timer不是一种实时的机制,会存在延迟。

    不积跬步,无以至千里;不积小流,无以成江海。
  • 相关阅读:
    html5--6-10 CSS选择器7--伪类选择器
    html5--6-9 CSS选择器6--伪类选择器
    html5--6-8 CSS选择器5
    避开美国全球监控阴影下的问题手机,寻求新伙伴
    DMA过程分析
    混淆
    Missile:双状态DP
    Java抓取网页数据(原网页+Javascript返回数据)
    Binders 与 Window Tokens(窗体令牌)
    编程之美2013 初赛一 A
  • 原文地址:https://www.cnblogs.com/xiaocai-ios/p/7779794.html
Copyright © 2011-2022 走看看