ios程序进入后台(按下home键)进程便会立即挂起,如果使用了socket连接,这时socket没有了可用的进程,便会导致连接失败,甚至程序崩溃。
如果我们希望程序在后台继续运行,我们便要在程序进入后台时进行适当的操作,以阻止进程挂起。下面以保持后台长连接为例,说明iOS无限后台任务的实现。
官方说只允许五种情况保持后台连接,具体见百度。无限制后台连接方法如下:
先在AppDelegate类中增加两个成员变量:
NSTimer *backgroundTimer;
UIBackgroundTaskIdentifier __block backgroundTask;
然后重写下面的方法:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[self backgroundHandler];
}
- (void)backgroundHandler
{
UIApplication * app = [UIApplicationsharedApplication];
backgroundTask = [app beginBackgroundTaskWithExpirationHandler:^{
if([backgroundTimerisValid])
[backgroundTimerinvalidate];
[app endBackgroundTask:backgroundTask];
backgroundTask = UIBackgroundTaskInvalid;
NSLog(@"后台持续时间:%f",[app backgroundTimeRemaining]);
}];
// Start the long-running task in the main tread
if(backgroundTask!=UIBackgroundTaskInvalid)
{
//你的后台任务
}
}
启动的后台任务不会有截止期,即不会执行到^{}里面,程序进入前台时需要将后台任务结束:
- (void)applicationWillEnterForeground:(UIApplication *)application
{
//进入前应该终止后台任务
if(backgroundTask!=UIBackgroundTaskInvalid)
{
NSLog(@"终止后台");
[backgroundTimerinvalidate];
[[UIApplicationsharedApplication]endBackgroundTask:backgroundTask];
backgroundTask = UIBackgroundTaskInvalid;
}
}
遗憾的是,上面的方法虽然可以执行后台任务,但重新进入前台的时候貌似程序程序仍 然会重新加载 一些东西,比如重新加载 启动图片,像app重新启动了一样,实际上app可以接着进入后台之前运行的。这说明后台还是释放了一些app资源?请高手指教 。
如果想避免进入前台重新加载那样的问题,可以使用下面的方法:
- (void)applicationDidEnterBackground:(UIApplication *)application
{BOOL backgroundAccepted = [[UIApplication sharedApplication] setKeepAliveTimeout:600 handler:^{
[self backgroundHandler];
}];
if (backgroundAccepted)
{
NSLog(@"background accepted");
[self backgroundHandler];
}
}
但是,上面使用的setKeepAliveTimeout:handler:方法适用于VoIP服务的app的,所以需要在Xcode项目中开启这个服务。
需要说明的是,这样又导致了一个问题:如果app中没有真正使用VoIP,提交app时不能通过审核。