iOS 定时器的使用以及注意事项

技术迁移:http://blog.csdn.net/iosbird/article/details/76360049
我在工程中写了一个方法

  • (void)timecount{
    NSDate* date = [NSDate date];
    NSDateFormatter formatter = [[NSDateFormatter alloc]init];
    [formatter setDateFormat:@"hh:mm:ss"];
    NSString time = [formatter stringFromDate:date];
    NSLog(@"%@",time);
    }
    用于打印时间字符串的
    首先定义一个变量
    NSTimer _timer;
    然后实现计时器功能
    利用
    NSTimer
    *
    方法1、创建并绑定计时器
    _timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timecount) userInfo:nil repeats:YES];
    效果如下:

    iOS 定时器的使用以及注意事项_第1张图片

    方法2、
    _timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(timecount) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop]addTimer:_timer forMode:NSDefaultRunLoopMode];
    iOS 定时器的使用以及注意事项_第2张图片

    注意,上面的runloop是在主线程中开启的,要在子线程开启,就需要手动开启了
    方法3、子线程中开启runloop
    [NSThread detachNewThreadSelector:@selector(useNSTimer) toTarget:self withObject:nil];
    实现方法useNSTimer

  • (void)useNSTimer{
    _timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(timecount) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop]addTimer:_timer forMode:NSRunLoopCommonModes];
    // runloop在子线程上是需要手动开启的
    [[NSRunLoop currentRunLoop] run];
    }
    如果要销毁子线程中的定时器,就要在子线程中调用销毁方法,否则会造成runloop资源的浪费

  • (void)useNSTimer{

    _timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(timecount) userInfo:nil repeats:YES];
    [self performSelector:@selector(stopcount) withObject:nil afterDelay:10];
    [[NSRunLoop currentRunLoop]addTimer:_timer forMode:NSRunLoopCommonModes];
    //// runloop在子线程上是需要手动开启的
    [[NSRunLoop currentRunLoop] run];
    }
    上面的代码就是在10秒后销毁定时器

  • (void)stopcount{
    [_timer invalidate];
    _timer = nil;
    }
    效果图如下:


    iOS 定时器的使用以及注意事项_第3张图片

    注意,runloop对timer有了强引用,weak型的timer不会被释放,所以要在适当的时候销毁timer对象
    上面的timer都会造成循环引用,我们可以给NSTimer扩展一个方法:
    定义并实现

  • (NSTimer *)timerWithTimeInterval:(NSTimeInterval)interval block:(void (^)())block repeats:(BOOL)repeats{
    return [NSTimer timerWithTimeInterval:interval target:self selector:@selector(timerSelector:) userInfo:block repeats:repeats];
    }
  • (void)timerSelector:(NSTimer *)timer{
    void (^ block)() =[timer userInfo];
    if (block) {
    block();
    }
    }
    在调用时倒入我们写的扩展
    __weak typeof(self)weakSelf = self;
    _timer = [NSTimer timerWithTimeInterval:1 block:^{
    [weakSelf timecount];
    } repeats:YES];
    [[NSRunLoop currentRunLoop]addTimer:_timer forMode:NSRunLoopCommonModes];
    [[NSRunLoop currentRunLoop] run];
    如此就避免了timer带来的循环引用问题

在iOS10以后,苹果提供了带block的方法就避免了循环引用
_timer = [NSTimer timerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {

}];

[[NSRunLoop currentRunLoop]addTimer:_timer forMode:NSRunLoopCommonModes];
或者
_timer = [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {

}];

利用GCD实现计时器

  • (void)usegcd:(NSTimeInterval)timeinterval repeats:(BOOL)repeats{
    __weak typeof(self)weakSelf = self;
    dispatch_queue_t queue = dispatch_queue_create("计时器", 0);
    dispatch_source_t time = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    dispatch_source_set_timer(time, DISPATCH_TIME_NOW, NSEC_PER_SEC, 0);
    dispatch_source_set_event_handler(time, ^{
    if (!repeats) {
    dispatch_cancel(time);
    }
    else
    [weakSelf timecount];
    });
    dispatch_resume(time);
    }

你可能感兴趣的:(iOS 定时器的使用以及注意事项)