iOS开发 | 清晰的倒计时button

作者: Lol刀妹 | 来源:发表于2018-03-10 11:26 被阅读897次
    图片来自网络

    这个button主要是针对获取短信验证码那一类倒计时按钮的封装。

    清晰,是指逻辑清晰。

    我将它的逻辑拆分成dataSourcedelegate两部分:

    #import <UIKit/UIKit.h>
    
    @class CQCountdownButton;
    
    @protocol CQCountDownButtonDataSource <NSObject>
    
    // 设置起始倒计时秒数
    - (NSInteger)startCountdownNumOfCountdownButton:(CQCountdownButton *)countdownButton;
    
    @end
    
    @protocol CQCountDownButtonDelegate <NSObject>
    
    // 倒计时按钮点击时回调
    - (void)countdownButtonDidClick:(CQCountdownButton *)countdownButton;
    // 倒计时进行中的回调
    - (void)countdownButtonDidCountdown:(CQCountdownButton *)countdownButton withRestCountdownNum:(NSInteger)restCountdownNum;
    // 倒计时结束时的回调
    - (void)countdownButtonDidEndCountdown:(CQCountdownButton *)countdownButton;
    
    @end
    
    @interface CQCountdownButton : UIButton
    
    @property (nonatomic, weak) id <CQCountDownButtonDataSource> dataSource;
    @property (nonatomic, weak) id <CQCountDownButtonDelegate> delegate;
    
    /** 开始倒计时 */
    - (void)startCountDown;
    /** 释放timer */
    - (void)releaseTimer;
    
    @end
    

    使用如下:

    代码组织
    #import "CQCountdownButton.h"
    
    @interface SecondViewController () <CQCountDownButtonDataSource, CQCountDownButtonDelegate>
    
    @property (nonatomic, strong) CQCountdownButton *countdownButton;
    
    @end
    
    @implementation SecondViewController
    
    #pragma mark - Life Cicle
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        
        self.title = @"第二页";
        
        self.countdownButton = [[CQCountdownButton alloc] initWithFrame:CGRectMake(90, 200, 200, 30)];
        [self.view addSubview:self.countdownButton];
        [self.countdownButton setTitle:@"点击获取验证码" forState:UIControlStateNormal];
        self.countdownButton.backgroundColor = [UIColor blueColor];
        self.countdownButton.dataSource = self;
        self.countdownButton.delegate = self;
    }
    
    - (void)dealloc {
        [self.countdownButton releaseTimer];
        NSLog(@"页面二已释放");
    }
    
    #pragma mark - CQCountdownButton DataSource
    
    // 设置倒计时总秒数
    - (NSInteger)startCountdownNumOfCountdownButton:(CQCountdownButton *)countdownButton {
        return 60;
    }
    
    #pragma mark - CQCountdownButton Delegate
    
    // 倒计时按钮点击
    - (void)countdownButtonDidClick:(CQCountdownButton *)countdownButton {
        // 按钮点击后将enabled设置为NO
        countdownButton.enabled = NO;
        countdownButton.backgroundColor = [UIColor grayColor];
        // 请求短信验证码
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [countdownButton startCountDown];
        });
    }
    
    // 倒计时进行中
    - (void)countdownButtonDidCountdown:(CQCountdownButton *)countdownButton withRestCountdownNum:(NSInteger)restCountdownNum {
        NSString *title = [NSString stringWithFormat:@"%ld秒后重新获取", restCountdownNum];
        [countdownButton setTitle:title forState:UIControlStateNormal];
    }
    
    // 倒计时结束
    - (void)countdownButtonDidEndCountdown:(CQCountdownButton *)countdownButton {
        [self.countdownButton setTitle:@"点击获取验证码" forState:UIControlStateNormal];
        countdownButton.backgroundColor = [UIColor blueColor];
        countdownButton.enabled = YES;
    }
    
    @end
    

    这个倒计时button的具体实现如下:

    #import "CQCountdownButton.h"
    
    @interface CQCountdownButton ()
    
    @property (nonatomic, strong) NSTimer *timer;
    
    @end
    
    @implementation CQCountdownButton {
        // 剩余倒计时
        NSInteger _restCountDownNum;
    }
    
    - (instancetype)initWithFrame:(CGRect)frame {
        if (self = [super initWithFrame:frame]) {
            [self addTarget:self action:@selector(onClick) forControlEvents:UIControlEventTouchUpInside];
        }
        return self;
    }
    
    // 按钮点击
    - (void)onClick {
        if ([self.dataSource respondsToSelector:@selector(startCountdownNumOfCountdownButton:)]) {
            _restCountDownNum = [self.dataSource startCountdownNumOfCountdownButton:self];
        }
        if ([self.delegate respondsToSelector:@selector(countdownButtonDidClick:)]) {
            [self.delegate countdownButtonDidClick:self];
        }
    }
    
    // 开始倒计时
    - (void)startCountDown {
        if (self.timer) {
            [self releaseTimer];
        }
        
        self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(refreshButton) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
    }
    
    // 刷新按钮
    - (void)refreshButton {
        _restCountDownNum --;
        
        if ([self.delegate respondsToSelector:@selector(countdownButtonDidCountdown:withRestCountdownNum:)]) {
            [self.delegate countdownButtonDidCountdown:self withRestCountdownNum:_restCountDownNum];
        }
        
        if (_restCountDownNum == 0) {
            [self releaseTimer];
            
            if ([self.delegate respondsToSelector:@selector(countdownButtonDidEndCountdown:)]) {
                [self.delegate countdownButtonDidEndCountdown:self];
            }
        }
    }
    
    - (void)releaseTimer {
        if (self.timer) {
            [self.timer invalidate];
            self.timer = nil;
        }
    }
    
    - (void)dealloc {
        NSLog(@"倒计时按钮已释放");
    }
    
    @end
    

    demo:
    https://github.com/CaiWanFeng/ClearCountdownButton

    相关文章

      网友评论

      • 玩呀玩:Facebook/pop 了解一下?
        几行代码就能搞定
        Lol刀妹:必须了解一下:sunglasses:
      • Lol刀妹:关于CepheusSun的提问。1.为什么要用datasource?答:参照UITableView;2.用 @Optional 修饰下?答:那几个代理方法都是必须实现的,默认是@required,所以省略。
      • 叶熙雯:为啥要写这么麻烦呢?
        Lol刀妹:@叶熙雯 不麻烦吧。。。就是封装了一下倒计时那一块的逻辑,结合delegate这样看起就清晰多了
      • 玉思盈蝶:感觉周报落了好多了:sob:
        Lol刀妹:准备下周写:smile:
      • 娘亲Joanna:终于更帖了:no_mouth:
        Lol刀妹:坚持周更:sweat_smile:
      • CepheusSun:明明一个属性赋值就解决的问题,为什么要用datasource呢? 然后 delegate 里面,如果不是必须实现的方法,还是用 @Optional 修饰下撒。最后强烈建议快师傅看一下孙源之前写的 self manager 模式,欧阳偶像还写过一篇学习心得。感觉这就是一种使用 self manager 的场景。徒儿学艺不经,还请快师傅见谅
        Lol刀妹:可以,学习了:sunglasses:

      本文标题:iOS开发 | 清晰的倒计时button

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