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

来源:互联网 发布:2017最新网络灰色项目 编辑:程序博客网 时间:2024/05/22 14:41


我在工程中写了一个方法

- (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];

效果如下:


方法2

 _timer = [NSTimer timerWithTimeInterval:1 target:self  selector:@selector(timecount) userInfo:nil repeats:YES];

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


注意,上面的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;

}

效果图如下:


注意,runlooptimer有了强引用,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);

}



原创粉丝点击