zoukankan      html  css  js  c++  java
  • NSTimer的使用

     NSTimer其实是将一个监听加入到系统的RunLoop中去,当系统runloop到如何timer条件的循环时,会调用timer一次,当timer执行完,也就是回调函数执行之后,timer会再一次的将自己加入到runloop中去继续监听。

    定义一个timer:

    NSTimer *timer=[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(onTimer) userInfo:nil repeats:YES];

    常用方法:

    [timer fire];// 可以通过fire这个方法去触发timer,让其立即执行,即使timer的firing time没有到达 

    [timer invalidate]; //停止并删除,将计时器从runloop中移出的方法。一般由Runloop控制,不需自己设置

    [timer  setFireDate:[NSDate  distantFunture]];//暂停执行

    [timer setFireDate:[NSDate date]];//继续执行

    [timer setFireDate:[NSDate  distantPast]];//开启

    开启方法和继续方法有什么差别呢?

     

    @interface NSTimer : NSObject
    //初始化,最好用scheduled方式初始化,不然需要手动addTimer:forMode: 将timer添加到一个runloop中。
    + (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
    + (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
    
    + (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
    + (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
    
    - (id)initWithFireDate:(NSDate *)date interval:(NSTimeInterval)ti target:(id)t selector:(SEL)s userInfo:(id)ui repeats:(BOOL)rep;
    
    - (void)fire;  //立即触发定时器
    
    - (NSDate *)fireDate;//开始时间
    - (void)setFireDate:(NSDate *)date;//设置fireData,其实暂停、开始会用到
    
    - (NSTimeInterval)timeInterval;//延迟时间
    
    - (void)invalidate;//停止并删除
    - (BOOL)isValid;//判断是否valid
    
    - (id)userInfo;//通常用nil
    
    @end

    在invalidate之前最好先用isValid先判断是否还在线程中:

    
    
    if ([scrollTimer isValid] == YES) {
            [scrollTimer invalidate];
            scrollTimer = nil;
    }
     

    NSTimer invalidate后再isValid程序崩溃

    在使用NSTimer的时候,如果我调用了invalidate,然后在使用isValid判断当前timer的状态,就会出现内存无效引用,程序崩溃。原因是,NSTimer是一个自动释放的对象,当调用invalidate的时候会自动把该对象释放掉,所以再调用isValid的时候就会提示引用无效地址了。解决的办法是在每次调用invalidate之后把该timer设置为nil,然后在要调用isValid的时候直接判断该timer是不是nil就ok了。苯方法,但是解决我的需求!
     
    self.m_timerTimeOut = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self
                                                          selector:@selector(handleTimeOutAction) userInfo:nil repeats:YES];

    第一个参数,1.0代表1秒,如果该值<0,系统会默认为0.1 
    第二个参数, target:(id)aTarget,表示发送的对象,如self 
    第三个参数,selector:(SEL)aSelector方法选择器,在时间间隔内,选择调用一个实例方法 
    第四个参数,userInfo:(id)userInfo此参数可以为nil,当定时器失效时,由你指定的对象保留和释放该定时器。 
    第五个参数,repeats:(BOOL)yesOrNo当YES时,定时器会不断循环直至失效或被释放,当NO时,定时器会循环发送一次就失效。 

    iphone NSTimer invalidate 和 release 释放问题 
    最近在使用NSTimer的时候,遇到了一些内存错误的问题,找了一片很好的文章可惜是英文的,现自己翻译出来,以备后用。 
    原文: 
    [timer release] only needs to be called if you “own” the timer. From Apple’s documentation: 
    Because the run loop maintains the timer, from the perspective of memory management there’s typically no need to keep a reference to a timer once you’ve scheduled it. Since the timer is passed as an argument when you specify its method as a selector, you can invalidate a repeating timer when appropriate within that method. In many situations, however, you also want the option of invalidating the timer—perhaps even before it starts. In this case, you do need to keep a reference to the timer, so that you can send it an invalidate message whenever is appropriate. If you create an unscheduled timer (see “Unscheduled Timers”), then you must maintain a strong reference to the timer (in a reference-counted environment, you retain it) so that it is not deallocated before you use it. 
    What does this mean? 
    If you alloc and init a timer, you must also release it, like so: 
    NSTimer * timer = [[NSTimer alloc] initWith…]; 
    NSRunLoop * runLoop = [NSRunLoop currentRunLoop]; 

    [runLoop addTimer:timer forMode:NSDefaultRunLoopMode]; 

    [timer release]; 
    …… 
    [timer invalidate]; 

    timer = nil; 

    Once the timer has been added to the run loop, there is no reason to keep a reference to it anymore, since the run loops owns it. In this case, as shown, you would release the timer as soon as you add it to the run loop, and then simplyinvalidate it when you are finished. The final line (setting timer to nil) is for safety. The call to invalidate will result in the timer being released (by the run loop), so it is unsafe to keep a reference that points to it. Setting the local reference to nil keeps things kosher. 
    If, however, you create a timer using one of the convenience methods like so: 
    NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval ...]; 

    You do not need to call [timer release] at all! 

    The convenience method adds the timer to the run loop, which then owns it, so you do not need to perform any memory management on the returned timer object. You would simplyinvalidate the timer when you no longer want to use it: 
    [timer invalidate];timer = nil; 

    Or, if the timer was not set to repeat, you would do absolutely nothing at all, since it would be released after its first invocation. 

    译文:[timer release]这个方法只有在当你拥有timer的时候才可以调用。根据Apple的文档描述如下:由于RunLoop保持着timer。从内存管理的角度上看,当我们scheduled(预定)一个timer的时候,我们通常是不需要保持它的reference(引用计数)的。由于timer是作为一个参数传递的,timer的指定的方法是selector的形式,所以你可以在指定的方法的内部,在合适的时候invalidate一个重复的timer(repeating timer)。然而,在许多的场合下,你可能会想在timer开始之前就invalidating timer。在这种情况下,又必须保持一个对timer的引用(reference),以便于你可以合适的时间向timer发送invalidate消息。如果你创建了一个 unscheduled timer,你必须保持一个对于这个timer的 strong reference(在 reference_count(引用计数的环境下),你给timer发送了一个retain的消息),n这样做目的是保证在你使用该timer之前,它不会被deallocated。简言之:如果你allloc init了一个timer,你必须release it,例如: 
    NSTimer * timer = [[NSTimer alloc] initWith…]; 
    NSRunLoop * runLoop = [NSRunLoop currentRunLoop]; 
    [runLoop addTimer:timer forMode:NSDefaultRunLoopMode]; 
    [timer release]; 
    …… 
    [timer invalidate]; 
    timer = nil; 
    一旦timer被加入了Runloop,我们就没有任何原因来保持一个引用,因为Runloop会保持它。在这个展示中,正如我们我展示的,你应该release 掉它,当你把它添加进Runloop的时候,并且像示例中的那样在timer结束的时候 invalidate 。最后一行代码(timer = nil)是为了安全。invalidate 的调用会使得timer被release(由Runloop控制),所以保持一个指向timer的引用是不安全。将本地的引用设置为空是符合规则的。 
    无论如何,如果你创建一个timer按照下面的这种形式: 
    NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval ...]; 
    你根本不需要 调用 [timer release]! 
    这个便捷的方法,把timer加入到了Runloop,Runloop会保持timer的引用计数,所以你不需要在返回的timer对象上实现任何的 
    内存管理。你应该想示例的那样invalidate timer,如下: 
    [timer invalidate];timer = nil; 
    或者,如果timer没有设置重复(repeat),你就安心的不需要做任何的事情,因为他会在第一次调用完成后release timer。

     

    转自http://www.cnblogs.com/ios-wmm/archive/2012/08/24/2654779.html 

  • 相关阅读:
    linux ls
    ExtJs 弹出窗口
    Redhat5 装中文
    Linux下配置JDK以及报cannot restore segment prot after reloc: Permission denied错解决方案
    工具
    得到剪切的图片
    label button等设置不同颜色的标题
    UITableView UITextField 键盘挡住
    给出颜色生成图片
    一个不错的学习网站
  • 原文地址:https://www.cnblogs.com/lvchenhao/p/4242295.html
Copyright © 2011-2022 走看看