.h
/**
时间改变时执行
@param timeArray
天
,
时
,
分
,
秒
数组
*/
typedef
void
(^TimeChangeBlock)(
NSMutableArray
*timeArray);
.m
/**
倒计时
@param endTimeStep
倒计时一共有多少时间
(
秒
)
@param timeChange
每次时间改变时执行
@param timeEnd
时间归
0
是执行
*/
- (
void
)countDownTime:(
NSInteger
)endTimeStep withTimeChange:(
TimeChangeBlock
)timeChange withTimeEnd:(
TimeChangeBlock
)timeEnd{
__block
NSInteger
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 = [
NSMutableArray
arrayWithCapacity
:
0
];
[timeArray
addObject
:[
NSNumber
numberWithInteger
:days]];
[timeArray
addObject
:[
NSNumber
numberWithInteger
:hours]];
[timeArray
addObject
:[
NSNumber
numberWithInteger
:minute]];
[timeArray
addObject
:[
NSNumber
numberWithInteger
: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
){
[
self
endBackGroundTask
];
}
});
}];
}
- (
void
)applicationDidEnterBackground:(
UIApplication
*)application {
[
super
applicationDidEnterBackground
: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.
[
self
beginBackGroundTask
:application];
}
- (
void
)applicationWillEnterForeground:(
UIApplication
*)application {
[
super
applicationWillEnterForeground
: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;
[
self
endBackGroundTask
];
}
//
结束程序进入后台的任务
- (
void
)endBackGroundTask {
//
每个对
beginBackgroundTaskWithExpirationHandler:
方法的调用
,
必须要相应的调用
endBackgroundTask:
方法。这样,来告诉应用程序你已经执行完成了。
//
也就是说
,
我们向
iOS
要更多时间来完成一个任务
,
那么我们必须告诉
iOS
你什么时候能完成那个任务。
//
也就是要告诉应用程序:
“
好借好还
”
嘛。
//
标记指定的后台任务完成
[[
UIApplication
sharedApplication
]
endBackgroundTask
:
self
.
bgIdentifier
];
//
销毁后台任务标识符
self
.
bgIdentifier
=
UIBackgroundTaskInvalid
;
}