倒计时封装 程序进入后台不会暂停计时器

来源:互联网 发布:2016欧洲杯数据 编辑:程序博客网 时间:2024/05/21 10:43


.h
/**
 时间改变时执行

 @param timeArray,,,数组
 */
typedefvoid(^TimeChangeBlock)(NSMutableArray *timeArray);

.m
/**
 倒计时

 @param endTimeStep倒计时一共有多少时间()
 @param timeChange每次时间改变时执行
 @param timeEnd时间归0是执行
 */
- (void)countDownTime:(NSInteger )endTimeStep withTimeChange:(TimeChangeBlock)timeChange withTimeEnd:(TimeChangeBlock)timeEnd{
    __blockNSInteger timeout = endTimeStep/1000;//倒计时时间
   
    //队列(队列时用来确定该定时器存在哪个队列中)
    dispatch_queue_t queue =dispatch_get_main_queue();
    //创建GCD定时器
    dispatch_source_t timer =dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,0,0, queue);
   
    //    _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    dispatch_time_t start =dispatch_time(DISPATCH_TIME_NOW,0 *NSEC_PER_SEC);//开始时间
    uint64_t interval =1 *NSEC_PER_SEC;//时间间隔
   
    //设置GCD定时器开始时间,间隔时间
    dispatch_source_set_timer(timer, start, interval,0);
   
    // GCD定时器处理回调方法
    dispatch_source_set_event_handler(timer, ^{

        NSInteger days = timeout/(3600*24);
        NSInteger hours = (timeout-days*24*3600)/3600;
        NSInteger minute = (timeout-days*24*3600-hours*3600)/60;
        NSInteger second = timeout-days*24*3600-hours*3600-minute*60;
       
        NSMutableArray *timeArray = [NSMutableArrayarrayWithCapacity:0];
        [timeArrayaddObject:[NSNumbernumberWithInteger:days]];
        [timeArrayaddObject:[NSNumbernumberWithInteger:hours]];
        [timeArrayaddObject:[NSNumbernumberWithInteger:minute]];
        [timeArrayaddObject:[NSNumbernumberWithInteger:second]];

        if (timeChange) {
            timeChange(timeArray);
        }

        timeout--;
        if (timeout<0) {//时间归0
           //关闭定时器
           dispatch_cancel(timer);
           if (timeEnd) {
                timeEnd(timeArray);
            }
        }
    });
   
    // GCD定时器启动,默认是关闭的
    dispatch_resume(timer);
}



appdelegate.m
#pragma mark -程序进入后台后继续倒计时功能
//程序进入后台不会影响到计时功能
- (void)beginBackGroundTask:(UIApplication *)application {
    self.bgIdentifier =[application beginBackgroundTaskWithExpirationHandler:^(void) {
       
        //当应用程序留给后台的时间快要到结束时(应用程序留给后台执行的时间是有限的),这个Block块将被执行
        //我们需要在次Block块中执行一些清理工作。
        //如果清理工作失败了,那么将导致程序挂掉
        //清理工作需要在主线程中用同步的方式来进行
        dispatch_queue_t mainQueue =dispatch_get_main_queue();
        AppDelegate *weakSelf =self;
        dispatch_async(mainQueue, ^(void) {
           
           AppDelegate *strongSelf = weakSelf;
           if (strongSelf !=nil){
                [selfendBackGroundTask];
            }
        });
    }];
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    [superapplicationDidEnterBackground: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.
   
    [selfbeginBackGroundTask:application];
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
    [superapplicationWillEnterForeground:application];
    // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    //application.applicationIconBadgeNumber = 0;
   
    [selfendBackGroundTask];
   
}
//结束程序进入后台的任务
- (void)endBackGroundTask {
    //每个对 beginBackgroundTaskWithExpirationHandler:方法的调用,必须要相应的调用 endBackgroundTask:方法。这样,来告诉应用程序你已经执行完成了。
    //也就是说,我们向 iOS 要更多时间来完成一个任务,那么我们必须告诉 iOS 你什么时候能完成那个任务。
    //也就是要告诉应用程序:好借好还嘛。
    //标记指定的后台任务完成
    [[UIApplicationsharedApplication]endBackgroundTask:self.bgIdentifier];
    //销毁后台任务标识符
    self.bgIdentifier = UIBackgroundTaskInvalid;
}

阅读全文
0 0