iOS 分類之按鈕倒計時UIButton+CountDown

UIButton+CountDown.h


#import <UIKit/UIKit.h>

typedef void(^RunBlock)(UIButton *button, NSInteger totalTime, NSInteger leftTime);
typedef void(^EndBlock)(UIButton *button);

@interface UIButton (CountDown)

/**
 *  倒計時按鈕
 *
 *  @param duration 總時間
 *  @param runBlock 倒計時期間回調
 *  @param endBlock 倒計時結束回調
 */
- (void)startWithDuration:(NSInteger)duration
                  running:(RunBlock)runBlock
                 finished:(EndBlock)endBlock;
@end

UIButton+CountDown.m


#import "UIButton+CountDown.h"

@implementation UIButton (CountDown)

- (void)startWithDuration:(NSInteger)duration running:(RunBlock)runBlock finished:(EndBlock)endBlock
{
    __block NSInteger timeOut = duration;
    dispatch_queue_t queue    = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_source_t _timer  = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);

    dispatch_source_set_timer(_timer, dispatch_walltime(NULL, 0), 1.0 * NSEC_PER_SEC, 0);
    dispatch_source_set_event_handler(_timer, ^{

        if (timeOut <= 0) {

            dispatch_source_cancel(_timer);
            dispatch_async(dispatch_get_main_queue(), ^{
                endBlock(self);
            });
        } else {

            int allTime = (int)duration + 1;
            int seconds = timeOut % allTime;
            dispatch_async(dispatch_get_main_queue(), ^{
                runBlock(self, duration, seconds);
            });
            timeOut--;
        }
    });
    dispatch_resume(_timer);
}

@end

Tips: 

倒計時除了GCD還可以使用NSTimer實現,但是有一個問題,也是我的測試反饋的:

應用進入後臺一段時間,倒計時不工作,它只會從上一次消失的時間開始繼續工作。

朋友們可以搜索“NSTimer 進入後臺”,網上是說:進入後臺,定時器線程被掛起,進入前臺才繼續工作。

所以,如果你有這方面的需求,而且是在不影響其他工作(比如音視頻播放),可以在 AppDelegate.m 中添加如下代碼:

- (void)applicationDidEnterBackground:(UIApplication *)application {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.

    __block UIBackgroundTaskIdentifier backgroundTask;

    backgroundTask = [application beginBackgroundTaskWithExpirationHandler:^{
        dispatch_async(dispatch_get_main_queue(), ^{
            if (backgroundTask != UIBackgroundTaskInvalid)
            {
                backgroundTask = UIBackgroundTaskInvalid;
            }
        });
    }];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        dispatch_async(dispatch_get_main_queue(), ^{
            if (backgroundTask != UIBackgroundTaskInvalid)
            {
                backgroundTask = UIBackgroundTaskInvalid;
            }
        });
    });
}

參考文章:

iOS程序進入後臺後仍運行定時器NSTimer

NSTimer 鎖屏以及進入後臺不調用的解決方案

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章