iOS-倒计时实现的三种方式

作者: FlyElephant | 来源:发表于2017-09-30 20:07 被阅读209次

    倒计时实现由三种方式,一种是NSTimer,第二种是是CADisplayLink,第三中是通过GCD的方式来实现,效果图如下:

    倒计时.gif

    NSTimer

    NSTimer作为倒计时有两个重要的执行方式:

    + (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;
    + (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;
    

    倒计时代码:

    - (void)setupTimer {
        self.topLabel.text = [NSString stringWithFormat:@"%ld",topCount];
        self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(updateTopLabel) userInfo:nil repeats:YES];
    }
    
    - (void)updateTopLabel {
        topCount -= 1;
        self.topLabel.text = [NSString stringWithFormat:@"%ld",topCount];
        if (topCount == 0) {
            [self.timer invalidate];
        }
    }
    

    CADisplayLink

    CADisplayLink是一个能够和屏幕刷新率相同的频率将内容画到屏幕上的定时器.我们在应用中创建一个新的 CADisplayLink 对象,把它添加到一个runloop中,并给它提供一个 target 和selector 在屏幕刷新的时候调用.

    初始化CADisplayLink:

      self.midLabel.text = @"60";
        self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateMidLabel)];
        [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
    

    CADisplayLink每秒执行60次,除以60根据余数是否是0来判断是否过了一秒:

    - (void)updateMidLabel {
        midCount += 1;
        
        if (midCount % 60 == 0) {
            NSInteger result = 60 - midCount / 60;
            self.midLabel.text = [NSString stringWithFormat:@"%ld",result];
            if (result == 0) {
                [self.displayLink invalidate];
            }
    
        }
    }
    

    控制器即将消失的时候销毁Timer和DisplayLink,避免控制器不释放:

    - (void)viewDidDisappear:(BOOL)animated {
        [super viewDidDisappear:animated];
        if ([self.timer isValid]) {
            [self.timer invalidate];
        }
        
        [self.displayLink invalidate];
    }
    

    GCD

    GCD实现倒计时的方式,相对其他两种复杂一点,dispatch_source_set_timer设置倒计时,dispatch_source_set_event_handler设置倒计时执行的任务.

    - (void)setupGCD {
    
        self.bottomLabel.text = @"60";
        __block NSInteger bottomCount = 61;
        
        //获取全局队列
        dispatch_queue_t global = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        
        //创建一个定时器,并将定时器的任务交给全局队列执行
        dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, global);
        
        // 设置触发的间隔时间 1.0秒执行一次 0秒误差
        dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
    
        __weak typeof(self)weakSelf = self;
    
        dispatch_source_set_event_handler(timer, ^{
    
            if (bottomCount <= 0) {
                //关闭定时器
                dispatch_source_cancel(timer);
            }else {
                bottomCount -= 1;
                dispatch_async(dispatch_get_main_queue(), ^{
                    weakSelf.bottomLabel.text = [NSString stringWithFormat:@"%ld",bottomCount];
                });
            }
        });
        
        dispatch_resume(timer);
    }
    

    UI初始化:

    @interface DetailViewController () {
        NSInteger topCount;
        NSInteger midCount;
    }
    
    @property (weak, nonatomic) IBOutlet UILabel *topLabel;
    
    @property (weak, nonatomic) IBOutlet UILabel *midLabel;
    
    @property (weak, nonatomic) IBOutlet UILabel *bottomLabel;
    
    
    @property (strong, nonatomic) NSTimer *timer;
    
    @property (strong, nonatomic) CADisplayLink *displayLink;
    
    @end
    

    相关文章

      网友评论

        本文标题:iOS-倒计时实现的三种方式

        本文链接:https://www.haomeiwen.com/subject/jxtgcxtx.html