IOS 倒计时 按钮

1.写在前面[可以不用看]:

关于从前到现在写倒计时按钮的一些经历

最初:写的倒计时按钮就是用timer实现的,然后在周期触发的函数里面将记录的秒数 _second--, 这样做是可以解决简单的需求的。但是如果App在倒计时的时候进入到后台。此时倒计时的timer就不会执行了。只有当App重新从后台切换到前台的时候 timer才会继续执行。这样记录的时间显然就错了。因为没有减去中间在后台的那部分时间。


中期:由于初期遇到的问题,后来我想既然如此 就记录用户在进入后台时的时间A,然后进入前台时记录此时的时间B, 通过计算这两个时间的时间差,然后用此时倒计时的时间减去这个时间差来精确倒计时。 这样的确可以解决问题。 恶心的事情就是 还要去监听App前台后台的切换,还要定义多个变量去计算这个时间差。。。


后来:就是现在本文使用的方法,其实大致和中期的差不多,只是省略了计算前后台时间差的步骤。

原理:在timer初始化的时候记录了一个时间A,然后在周期触发的函数中每次都会获取一遍当前的时间,通过计算时间A到当前时间所花费的时间B,然后用倒计时的总时间减去这个时间B 就得到了倒计时剩余的时间。这样就可以达到要求了。而且实现起来也很简单。


最后说一下内存释放的问题:大家都知道 在使用timer的时候 有意个不好的地方就是在不使用的时候 如果不主动调用 [timer invalidate] 该时间对象是不会释放的。所以我这里也会去调用这个方法来释放内存。


封装的代码里面 会在倒计时技术的时候 自动调用一遍 [timer invalidate] ,及时用户当前界面pop了也没有关系,因为timer还在继续执行[这个地方貌似更runloop的机制有关,管兴趣的朋友可以百度 或者 google]


封装的方法里面也提供了主动释放资源的方法:cleanTimer


2:show my code 正题

头文件

#import <UIKit/UIKit.h>



/**

 关于资源释放的问题:不用外界手动调用[timer invalidate]; 

 由于定时器开启之后倒计时到0就会调用[timer invalidate],及时在界面pop之后也一样。到时候资源就可以自动释放了

 */

@interface FXW_CountDownButton :UIButton



/**

 设置倒计时时间不设置的话 模式是60s

 */

@property (nonatomic,assign) NSInteger     countDownSecond;


/**

 定义代码块


 @param isStartCounting 开始倒计时

 @param isCounting      正在倒计时

 */

typedef void (^FXW_CountDownButtonBlock)(BOOL isStartCounting,BOOL isCounting);



/**

 点击事件回调

 

 @param block FXW_CountDownButtonBlock

 */

- (void)clickButtonWithResultBlock:(FXW_CountDownButtonBlock)block;



/**

 如果想要提前关闭定时器可以调用该方法。不是必要的操作

 */

- (void)cleanTimer;


@end


.m文件

#import "FXW_CountDownButton.h"


@interface FXW_CountDownButton()


@property (nonatomic,copy) FXW_CountDownButtonBlock            clickButtonCallback;


@property (nonatomic,assign) NSTimeInterval                    timeNum;

@property (nonatomic,strong) NSTimer                           *timer;

@property (nonatomic,strong) NSDate                            *startDate;



@end


@implementation FXW_CountDownButton


- (id)initWithFrame:(CGRect)frame

{

    self = [superinitWithFrame:frame];

    if (self)

    {

        //可以给不同的事件设置不同的block

        [selfaddTarget:selfaction:@selector(clickAction)forControlEvents:UIControlEventTouchUpInside];

        _countDownSecond =60;//设置默认倒计时时间为 60s

    }

    returnself;

    

}


#pragma mark 开始倒计时

- (void)startCountDown

{

    if (_timeNum <=0)

    {

        _timeNum =_countDownSecond;//设置默认倒计时时间为60s

    }

    

    if (_timer ==nil)//设置倒计时

    {

        //每间隔1s会去执行一次countDown

        _timer = [NSTimerscheduledTimerWithTimeInterval:1

                                                  target:self

                                                selector:@selector(countDown)userInfo:nilrepeats:YES];

        

        _startDate = [NSDatedate];//记录倒计时时的时间

//        [[NSRunLoop currentRunLoop]addTimer:_timer forMode:NSRunLoopCommonModes];

        

    }

    

    [selfsetTitle:[NSStringstringWithFormat:@"还剩%d", (int)_timeNum]forState:UIControlStateNormal];

    

}


#pragma mark 倒计时_周期调用 <=0停止倒计时 并恢复默认样式

- (void)countDown

{

    double deltaTime = [[NSDatedate] timeIntervalSinceDate:_startDate];//计算从开始倒计时到此刻的时间差

    

    _timeNum =_countDownSecond - (NSInteger)(deltaTime+0.5);

    

    [selfsetTitle:[NSStringstringWithFormat:@"还剩%d", (int)_timeNum]forState:UIControlStateNormal];

    

    if (_timeNum <=0)

    {

        

        [selfsetTitle:@"重新获取验证码"forState:UIControlStateNormal];

        _timeNum =_countDownSecond;

        

        [_timerinvalidate];

        _timer =nil;

        

    }

    

}



- (void)clickAction

{

    if (_clickButtonCallback)

    {

        if (_timeNum <=0 || _timeNum ==60)

        {

            [selfstartCountDown];

            _clickButtonCallback(YES,NO);

        }

        else//如果还在倒计时则不执行新的倒计时

        {

            NSLog(@"倒计时还在继续。。。");

            _clickButtonCallback(NO,YES);

        }

        

    }

    

}


- (void)clickButtonWithResultBlock:(FXW_CountDownButtonBlock)block

{

    _clickButtonCallback = block;

    

}


- (void)cleanTimer

{

    [_timerinvalidate];

    _timer =nil;

    

}


- (void)dealloc

{

    NSLog(@"倒计时按钮资源已释放");

}


@end


下面感谢开源项目提供者:https://github.com/shaojiankui/JKCountDownButton 为我提供的思路


下面写下我的项目地址:https://github.com/wokenshin/KenshinPro

猜你喜欢

转载自blog.csdn.net/wokenshin/article/details/72468005