您好,欢迎来到二三娱乐。
搜索
您的当前位置:首页iOS NSTimer

iOS NSTimer

来源:二三娱乐

NSTimer:依赖于 NSRunLoop的定时触发器,用于定时执行某个动作。

  • 创建
  • 暂停
  • 恢复
  • 销毁
  • 持续触发
创建:

只有把 NSTimer加入 NSRunLoop,NSTimer才会触发。

@property (nonatomic, retain) NSTimer *timer;

- (void)testNSTimer {

    // 方法一(常用):该方法会把 NSTimer加入 NSRunLoop
    _timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(output) userInfo:nil repeats:YES];

    // 方法二:新建 NSTimer,手动添加到 NSRunLoop
    _timer = [[NSTimer alloc] initWithFireDate:[NSDate date] interval:1.0f target:self selector:@selector(output) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode];

    // 方法三:新建 NSTimer,手动添加到 NSRunLoop
    _timer = [NSTimer timerWithTimeInterval:1.0f target:self selector:@selector(output) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode];

    // 子线程新建 NSTimer
    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        
        _timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(output) userInfo:nil repeats:YES];
        // 注意:子线程的 NSRunLoop默认是关闭的,需要run才会执行
        [[NSRunLoop currentRunLoop] run];
    }];
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperation:operation];

}

- (void)output {
    
    NSLog(@"fire");
}

暂停:
- (void)pauseTimer {
    
    if ([_timer isValid]) {
        // 在一个遥远的未来触发,即:暂停
        [_timer setFireDate:[NSDate distantFuture]];
    }
}
恢复:
- (void)resumeTimer {

    // 当前时间触发
    [_timer setFireDate:[NSDate date]];
}
销毁:invalidate

重复触发定时器时,如果不停止,它会一直执行下去,所以要在viewDidDisappear或者viewWillDisappear销毁它。

- (void)viewDidDisappear:(BOOL)animated {
    
    [super viewDidDisappear:animated];
    
    [_timer invalidate];
}

为什么不是在dealloc销毁?

首选,NSTimer创建的时候会强引用self(ViewController);NSTimer一直触发,就不会被销毁,它引用的ViewController也就不会执行dealloc方法,因此在dealloc方法中执行销毁动作是没有用的。

持续触发:

拖动UIScrollView会影响NSTimer的触发,把NSTimer加到NSRunLoopCommonModes即可解决。

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

什么是NSRunLoopCommonModes?为什么选它?

首先查看NSRunLoopCommonModes的官方解释:

Objects added to a run loop using this value as the mode are monitored by all run loop modes that have been declared as a member of the set of “common" modes

大概意思是:所有以添加对象到NSRunLoop的方式形成的NSRunLoopMode都会成为mode集合的一员,这个mode集合叫做NSRunLoopCommonModes。

也就是说 NSRunLoopCommonModes包含了几乎所有 NSRunLoopMode。

我们知道,使用方法一创建的NSTimer添加在 NSRunLoop的默认模式NSDefaultRunLoopMode,当拖动 UIScrollView时,NSRunLoop的模式会切换为NSEventTrackingRunLoopMode,它的官方解释如下:

A run loop should be set to this mode when tracking events modally, such as a mouse-dragging loop.

大概意思是:类似于拖拽鼠标的动作都会被计入 NSEventTrackingRunLoopMode。

那么处在 NSDefaultRunLoopMode模式的 NSTimer就不会继续触发。

所以把NSTimer加入NSRunLoopCommonModes的 NSRunLoop后不会受UIScrollView拖动的影响

Copyright © 2019- yule263.com 版权所有 湘ICP备2023023988号-1

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务