注:验证码倒计时按钮的应用是非常普遍的,该Blog就和你一起来写一个IDCountDownButton来实现验证码倒计时的效果。你可以想使用普通的UIButton类型按钮一样,只需要设置其倒计时时长(若未设置,默认为60秒),就可以轻松的实现点击countDownButton开始倒计时,倒计时结束方可重新点击。
如图
公有属性(public)
@interface IDCountDownButton : UIButton /** 验证码倒计时的时长 */ @property (nonatomic, assign) NSInteger durationOfCountDown; @end
私有属性
@interface IDCountDownButton () /** 保存倒计时按钮的非倒计时状态的title */ @property (nonatomic, copy) NSString *originalTitle; /** 保存倒计时的时长 */ @property (nonatomic, assign) NSInteger tempDurationOfCountDown; /** 定时器对象 */ @property (nonatomic, strong) NSTimer *countDownTimer; @end
需要屏蔽计时过程中,title更新时改变originalTitle的值
- (void)setTitle:(NSString *)title forState:(UIControlState)state { [super setTitle:title forState:state]; // 倒计时过程中title的改变不更新originalTitle if (self.tempDurationOfCountDown == self.durationOfCountDown) { self.originalTitle = title; } }
tempDurationOfCountDown的作用:倒计时;与durationOfCountDown配合判断当前IDCountDownButton是否具备重新开始倒计时的能力
- (void)setDurationOfCountDown:(NSInteger)durationOfCountDown { _durationOfCountDown = durationOfCountDown; self.tempDurationOfCountDown = _durationOfCountDown; }
设置IDCountDownButton默认的title为“获取验证码”
- (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { // 设置默认的倒计时时长为60秒 self.durationOfCountDown = 60; // 设置button的默认标题为“获取验证码” [self setTitle:@"获取验证码" forState:UIControlStateNormal]; } return self; } - (instancetype)initWithCoder:(NSCoder *)aDecoder { if (self = [super initWithCoder:aDecoder]) { // 设置默认的倒计时时长为60秒 self.durationOfCountDown = 60; // 设置button的默认标题为“获取验证码” [self setTitle:@"获取验证码" forState:UIControlStateNormal]; } return self; }
若tempDurationOfCountDown等于durationOfCountDown,说明未开始倒计时,响应并传递IDCountDownButton的点击事件;否则,不响应且不传递。
- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event { // 若正在倒计时,不响应点击事件 if (self.tempDurationOfCountDown != self.durationOfCountDown) { return NO; } // 若未开始倒计时,响应并传递点击事件,开始倒计时 [self startCountDown]; return [super beginTrackingWithTouch:touch withEvent:event]; }
创建定时器,开始倒计时
- (void)startCountDown { // 创建定时器 self.countDownTimer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(updateIDCountDownButtonTitle) userInfo:nil repeats:YES]; // 将定时器添加到当前的RunLoop中(自动开启定时器) [[NSRunLoop currentRunLoop] addTimer:self.countDownTimer forMode:NSRunLoopCommonModes]; }
更新IDCountDownButton的title为倒计时剩余的时间
- (void)updateIDCountDownButtonTitle { if (self.tempDurationOfCountDown == 0) { // 设置IDCountDownButton的title为开始倒计时前的title [self setTitle:self.originalTitle forState:UIControlStateNormal]; // 恢复IDCountDownButton开始倒计时的能力 self.tempDurationOfCountDown = self.durationOfCountDown; [self.countDownTimer invalidate]; } else { // 设置IDCountDownButton的title为当前倒计时剩余的时间 [self setTitle:[NSString stringWithFormat:@"%zd秒", self.tempDurationOfCountDown--] forState:UIControlStateNormal]; } }
移除定时器
- (void)dealloc { [self.countDownTimer invalidate]; }
添加vertificationCodeIDCountDownButton属性
@interface ViewController () /** 验证码倒计时的button */ @property (nonatomic, strong) IDCountDownButton *vertificationCodeIDCountDownButton; @end
创建vertificationCodeIDCountDownButton并进行相关设置
- (void)viewDidLoad { [super viewDidLoad]; // 创建vertificationCodeIDCountDownButton self.vertificationCodeIDCountDownButton = [[IDCountDownButton alloc] initWithFrame:CGRectMake(160, 204, 120, 44)]; // 添加点击事件 [self.vertificationCodeIDCountDownButton addTarget:self action:@selector(vertificationCodeIDCountDownButtonClick:) forControlEvents:UIControlEventTouchUpInside]; // 设置标题相关属性 [self.vertificationCodeIDCountDownButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [self.vertificationCodeIDCountDownButton setTitle:@"获取验证码" forState:UIControlStateNormal]; // 设置背景图片 [self.vertificationCodeIDCountDownButton setBackgroundImage:[UIImage imageNamed:@"redButton"] forState:UIControlStateNormal]; // 设置倒计时时长 self.vertificationCodeIDCountDownButton.durationOfCountDown = 10; // 将vertificationCodeIDCountDownButton添加的控制器的view中 [self.view addSubview:self.vertificationCodeIDCountDownButton]; }
实现点击事件触发的操作
- (void)vertificationCodeIDCountDownButtonClick:(UIButton *)button { // TODO:调用服务器接口,获取验证码 }
命名,以Icon开头(首字母大写), 跟上@2x/@3x ,如图:
尺寸,必须按要求设置尺寸,如图