在一些业务需求中,我们需要在app退出到后台或者杀死的时候做一些业务上的处理。在AppDelegate中提供了相关的方法。
APP进入后台
- (void)applicationDidEnterBackground:(UIApplication *)application
{
}
在后台进入到后台时会调起这个方法,我们可以在这个方法里做一些相关的处理。在app进入后台后几分钟应用会自动被杀死,applicationDidEnterBackground里我们可以调个方法监测到在后台应用即将被杀死的时候,并在应用被杀死前做业务上的相关处理。
// APP进入后台
- (void)applicationDidEnterBackground:(UIApplication *)application {
[[UIApplication sharedApplication]beginBackgroundTaskWithExpirationHandler:^{
//在应用杀死前在这里可以做出业务上的一些处理
}];
}
beginBackgroundTaskWithExpirationHandler的详细用法可以看这位大神的beginBackgroundTaskWithExpirationHandler
上面说的是应用进入到后台几分钟后被系统自动杀死的情况,但是还有种情况是应用被用户往上划手动杀死的。在应用被用户手动杀死时会AppDelegate调用下面的方法
-(void)applicationWillTerminate:(UIApplication *)application {
}
在这里需要注意一个问题:在applicationWillTerminate中做一些主线程的事情是没有问题,但是如果是做一些异步的处理,会发现应用杀死了,但是异步处理的事情并没有完成。比如我想在应用被手动杀死时向服务器发起请求,这个请求还没请求完应用就被杀死了,所以服务器接受不到客服端的请求。
-(void)applicationWillTerminate:(UIApplication *)application {
// 在应用杀死时向服务器发起请求,但是这里服务器接受不到客服端的请求,因为应用已经被杀死了
[[[YFServiceManager sharedManager] getPersonService]requestAnchorOnlineStateWithOnlineState:@"6" WithSuccess:^(id _Nonnull response) {
} withFailure:^(NSError * _Nonnull error) {
}];
}
小编在这里使用了信号量处理,将异步的网络请求达到了任务同步执行的要求
-(void)applicationWillTerminate:(UIApplication *)application {
//创建信号量
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[[[YFServiceManager sharedManager] getPersonService]requestAnchorOnlineStateWithOnlineState:@"6" WithSuccess:^(id _Nonnull response) {
//发起信号量
dispatch_semaphore_signal(semaphore);
} withFailure:^(NSError * _Nonnull error) {
//发起信号量
dispatch_semaphore_signal(semaphore);
}];
//等待信号量,如果没收到信号量主线程会被阻塞,应用不会被杀死。只有等到网络请求成功或失败后发起信号量,主线程接受到信号量,主线程才会被执行完,应用才会被杀死
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
信号量是一个非负整数,定义了两种原子操作:wait跟signal来进行访,信号量主要用于线程同步。当一个线程调用wait操作时,如果信号量的值大于0,则获得资源并将信号量值减一,如果等于0线程睡眠直到信号量值大于0或者超时;singal将信号量的值加1,如果这时候有正在等待的线程,唤醒该线程。
信号量的详细介绍和使用可以看这位大神的GCD信号量-dispatch_semaphore_t
至此监测应用被杀死的问题已经介绍完毕,但是小编还想再提几句,不想看的可以忽略。
beginBackgroundTaskWithExpirationHandler方法中做网络请求可以成功,并不需要做信号量处理。但是这个成功的前提是beginBackgroundTaskWithExpirationHandler方法是在applicationDidEnterBackground方法中执行的,如果是放在applicationWillTerminate方法中是不会的
这个不需要做信号量处理,网络请求仍然能成功
// APP进入后台
- (void)applicationDidEnterBackground:(UIApplication *)application {
[[UIApplication sharedApplication]beginBackgroundTaskWithExpirationHandler:^{
//在应用杀死前在这里可以做出业务上的一些处理
//这这里不需要做信号量的处理就能完成网络数据的请求
}];
}
网友评论