美文网首页ios 知识点网络请求搬砖
iOS实现倒计时的三种方式

iOS实现倒计时的三种方式

作者: 凌巅 | 来源:发表于2017-02-13 20:36 被阅读3317次

    iOS实现倒计时的三种方式

    做iOS app开发的过程当中,经常会出现获取验证码等需求,这个时候一般会使用倒计时来提示用户,本文主要总结iOS开发中常用的三种倒计时的实现方式。

    Thread方式实现

    NSTimer方式实现 (此种方式实现的时候,要注意Timer invalidate的时机,防止循环引用)

    GCD方式实现

    直接上代码吧

    #define TIMECOUNT 60
    
    @interface ViewController ()
    @property (strong, nonatomic) IBOutlet UIButton *firstBtn;
    @property (strong, nonatomic) IBOutlet UIButton *secondBtn;
    @property (strong, nonatomic) IBOutlet UIButton *thirdBtn;
    
    @property (assign, nonatomic) int count;
    @property (nonatomic, strong) NSTimer *timer;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        self.count = TIMECOUNT;
    }
    
    - (void)viewDidDisappear:(BOOL)animated {
        //页面消失的时候暂停定时器,防止出现循环引用,导致内存泄漏
        [self.timer invalidate];
    }
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    //------------***第一种方法***------------
    #pragma mark 线程Thread方式实现
    - (IBAction)firstBtnAction:(id)sender {
        //创建一个后台线程执行计时操作
        [self performSelectorInBackground:@selector(timerThread) withObject:nil];
    }
    
    - (void)timerThread {
        for (int i = TIMECOUNT; i >= 0 ; i--) {
            self.count--;
            //切换到主线程中更新UI
            [self performSelectorOnMainThread:@selector(updateFirstBtn) withObject:nil waitUntilDone:YES];
            sleep(1);
        }
    }
    
    //更新UI
    - (void)updateFirstBtn {
        NSString *str = nil;
        if (self.count == 0) {
            str = [NSString stringWithFormat:@"点击获取验证码"];
            self.firstBtn.userInteractionEnabled = YES;
        } else {
            str = [NSString stringWithFormat:@"%d秒后重新获取",self.count];
            self.firstBtn.userInteractionEnabled = NO;
        }
        [self.firstBtn setTitle:str forState:UIControlStateNormal];
    }
    
    //------------***第二种方法***------------
    #pragma mark NSTimer实现
    - (IBAction)secondBtnAction:(id)sender {
        self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(handleTimer) userInfo:nil repeats:YES];
    }
    //定时操作,更新UI
    - (void)handleTimer {
        if (self.count == 0) {
            self.secondBtn.userInteractionEnabled = YES;
            [self.secondBtn setTitle:[NSString stringWithFormat:@"点击获取验证码"] forState:UIControlStateNormal];
            self.count = TIMECOUNT;
            [self.timer invalidate];
        } else {
            self.secondBtn.userInteractionEnabled = NO;
            [self.secondBtn setTitle:[NSString stringWithFormat:@"%d秒后重新获取",self.count] forState:UIControlStateNormal];
        }
        self.count--;
    }
    
    //------------***第三种方法***------------
    /**
     *  1、获取或者创建一个队列,一般情况下获取一个全局的队列
     *  2、创建一个定时器模式的事件源
     *  3、设置定时器的响应间隔
     *  4、设置定时器事件源的响应回调,当定时事件发生时,执行此回调
     *  5、启动定时器事件
     *  6、取消定时器dispatch源,【必须】
     *
     */
    #pragma mark GCD实现
    - (IBAction)thirdBtnAction:(id)sender {
        __block NSInteger second = TIMECOUNT;
        //(1)
        dispatch_queue_t quene = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        //(2)
        dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, quene);
        //(3)
        dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
        //(4)
        dispatch_source_set_event_handler(timer, ^{
            dispatch_async(dispatch_get_main_queue(), ^{
                if (second == 0) {
                    self.thirdBtn.userInteractionEnabled = YES;
                    [self.thirdBtn setTitle:[NSString stringWithFormat:@"点击获取验证码"] forState:UIControlStateNormal];
                    second = TIMECOUNT;
                    //(6)
                    dispatch_cancel(timer);
                } else {
                    self.thirdBtn.userInteractionEnabled = NO;
                    [self.thirdBtn setTitle:[NSString stringWithFormat:@"%ld秒后重新获取",second] forState:UIControlStateNormal];
                    second--;
                }
            });
        });
        //(5)
        dispatch_resume(timer);
    }
    
    @end
    
    

    相关文章

      网友评论

      • iCodingBoy:你这个是不准确的,因为定时器到后台定制计时,你这个切换到后台,时间就不准确了
        PGOne爱吃饺子:@YZCoding 嗯嗯 谢谢啊,倒计时退出到后台的时候,就是会停止,谢谢啊
        iCodingBoy:@PGOne爱吃饺子 后台的话定时器会停止,也就是说你这个count不会计数,比如你要倒计时60s,在计时到10时定时器切换到后台50s,按理说回来了应该计时结束,但是实际上你这个还在计时,一般定时多少s需要使用时间戳对比,而不是count
        PGOne爱吃饺子:因为定时器到后台定制计时,你这个切换到后台,时间就不准确了 -----这句话可不可以说明白一点

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

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