OC:倒计时

核心思想:用CACurrentMediaTime方法获取到手机从开机一直到当前所经过的秒数,这个是不容易篡改的,而且从前台退到后台,再回到前台的过程中,CACurrentMediaTime一直在自增。

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface UIButton (MZCountdown)

- (void)mz_customCountDownWithTime:(NSInteger)timeNum endTitle:(NSString *)endTitle endTitleColor:(NSString *)endTitleColor endBgColor:(NSString *)endBgColor leftTimeBlock:(void (^)(NSInteger leftTime))block;
- (void)mz_countDownWithTime:(NSInteger)timeNum countingTitleColor:(NSString *)countingTitleColor countingFormat:(NSString *)countingFormat countingBgColor:(NSString *)countingBgColor endTitle:(NSString *)endTitle endTitleColor:(NSString *)endTitleColor endBgColor:(NSString *)endBgColor;

@end

NS_ASSUME_NONNULL_END


// .m
#import "UIButton+MZCountdown.h"

#import <objc/message.h>

@implementation UIColor (MZExtension)

+ (UIColor *)colorWithHex:(NSString *)hexColor alpha:(CGFloat)alpha {
    
    while ([hexColor hasPrefix:@"#"]) {
        hexColor = [hexColor substringFromIndex:1];
    }
    
    if ([hexColor length] < 6) {
        return nil;
    }
    
    unsigned int red, green, blue;
    NSRange range;
    range.length = 2;
    range.location = 0;
    [[NSScanner scannerWithString:[hexColor substringWithRange:range]] scanHexInt:&red];
    range.location = 2;
    [[NSScanner scannerWithString:[hexColor substringWithRange:range]] scanHexInt:&green];
    range.location = 4;
    [[NSScanner scannerWithString:[hexColor substringWithRange:range]] scanHexInt:&blue];
    return [UIColor colorWithRed:(float)(red/255.f) green:(float)(green / 255.f) blue:(float)(blue / 255.f) alpha:alpha];
}

+ (UIColor *)colorWithHex:(NSString *)hexColor {
    return [self colorWithHex:hexColor alpha:1.f];
}

@end


@interface UIButton ()

@property (nonatomic, strong) dispatch_source_t timer;

@end

@implementation UIButton (MZCountdown)

- (void)setTimer:(dispatch_source_t)timer {
    objc_setAssociatedObject(self, @selector(timer), timer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (dispatch_source_t)timer {
    return objc_getAssociatedObject(self, _cmd);
}


- (void)mz_countDownWithTime:(NSInteger)timeNum countingTitleColor:(NSString *)countingTitleColor countingFormat:(NSString *)countingFormat countingBgColor:(NSString *)countingBgColor endTitle:(NSString *)endTitle endTitleColor:(NSString *)endTitleColor endBgColor:(NSString *)endBgColor {
    
    //倒计时时间
    __block NSInteger timeOut = timeNum + CACurrentMediaTime() + 1;
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    
    //每秒执行一次
    dispatch_source_set_timer(self.timer, dispatch_walltime(NULL, 0), 1.0 * NSEC_PER_SEC, 0);
    dispatch_source_set_event_handler(self.timer, ^{
        NSInteger left = timeOut - CACurrentMediaTime();
        //倒计时结束,关闭
        if (left <= 0) {
            [self mz_cancelTimerWithTitle:endTitle titleColor:endTitleColor bgColor:endBgColor];
        } else {//倒计时中
            dispatch_async(dispatch_get_main_queue(), ^{
                if (countingBgColor) {
                    NSAssert(countingBgColor.length != 0, @"countingBgColor不能为空字符串");
                    self.layer.backgroundColor = [UIColor colorWithHex:countingBgColor].CGColor;
                }
                
                if (countingTitleColor) {
                    NSAssert(countingTitleColor.length != 0, @"countingTitleColor不能为空字符串");
                    [self setTitleColor:[UIColor colorWithHex:countingTitleColor] forState:UIControlStateNormal];
                }
                
                [self p_showLeftTimeWithFormat:countingFormat leftTime:left];
            });
        }
    });
    dispatch_resume(self.timer);
}

- (void)p_showLeftTimeWithFormat:(NSString *)countingFormat leftTime:(NSInteger)leftTime {
    if (!countingFormat || !countingFormat.length) {
        [self setTitle:[NSString stringWithFormat:@"%ld秒", leftTime] forState:UIControlStateNormal];
    } else {
        [self setTitle:[NSString stringWithFormat:countingFormat, leftTime] forState:UIControlStateNormal];
    }
    self.userInteractionEnabled = NO;
}

- (void)mz_customCountDownWithTime:(NSInteger)timeNum endTitle:(NSString *)endTitle endTitleColor:(NSString *)endTitleColor endBgColor:(NSString *)endBgColor leftTimeBlock:(void (^)(NSInteger leftTime))block {
    
    //倒计时时间
    __block NSInteger timeOut = timeNum + CACurrentMediaTime() + 1;
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    
    //每秒执行一次
    dispatch_source_set_timer(self.timer, dispatch_walltime(NULL, 0), 1.0 * NSEC_PER_SEC, 0);
    dispatch_source_set_event_handler(self.timer, ^{
        NSInteger left = timeOut - CACurrentMediaTime();
        //倒计时结束,关闭
        if (left <= 0) {
            [self mz_cancelTimerWithTitle:endTitle titleColor:endTitleColor bgColor:endBgColor];
        } else {//倒计时中
            dispatch_async(dispatch_get_main_queue(), ^{
                !block ?: block(left);
            });
        }
    });
    dispatch_resume(self.timer);
}

/** 取消倒计时 */
- (void)mz_cancelTimerWithTitle:(NSString *)title titleColor:(NSString *)titleColor bgColor:(NSString *)bgColor {
    
    if (!self.timer) {
        return;
    }
    
    dispatch_source_cancel(self.timer);
    dispatch_async(dispatch_get_main_queue(), ^{
        if (bgColor) {
            NSAssert(bgColor.length != 0, @"bgColor不能为空字符串");
            self.layer.backgroundColor = [UIColor colorWithHex:bgColor].CGColor;
        }
        
        if (titleColor) {
            NSAssert(titleColor.length != 0, @"titleColor不能为空字符串");
            [self setTitleColor:[UIColor colorWithHex:titleColor] forState:UIControlStateNormal];
        }
        
        [self setTitle:title forState:UIControlStateNormal];
        self.userInteractionEnabled = YES;
    });
}

@end
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容