一提到iOS后台机制,网上搜了下一大堆资料,众说纷纭,现结合苹果官方文档及自身实际对现阶段(iOS10)iOS后台技术做个梳理。APP应用状态分为激活、未激活、后台:

typedef NS_ENUM(NSInteger, UIApplicationState) {
    UIApplicationStateActive, // 前台
    UIApplicationStateInactive, //后台未在运行
    UIApplicationStateBackground //后台运行
} NS_ENUM_AVAILABLE_IOS(4_0);

本文要讨论就是UIApplicationStateBackground模式。Apple提供了以下三种方式:

  • 方式一:延长小段时间(beginBackgroundTaskWithName)
  • 方式二:系统托管下载任务(NSURLSession)
  • 方式三:特定类型APP(Audio、Location、VOIP、Bluetooth、Newsstand、External accessory、Background fetch、Remote notifications)

方式一:延长小段时间(beginBackgroundTaskWithName)

为了保证某些短任务能够顺序执行完成,iOS允许APP向系统申请一小段时间以供任务顺利完成,代码如下

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    bgTask = [application beginBackgroundTaskWithName:@"MyTask" expirationHandler:^{
    	//系统即将进入inactive
        [application endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    }];
 
	//主动结束
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
        [application endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    });
}

PS:beginBackgroundTaskWithName向系统申请延长休眠时间,endBackgroundTask表示系统可以进入休眠

需要注意的是:查了网上其他文章,都说可以最长申请600s的时间,但实际测试只有179s左右(应该跟系统有关,iOS6是600s,iOS7以上是180s,我的系统是iOS 10.0.1),可以通过backgroundTimeRemaining查询(打印是179.988913s),但没有找到可以设置的地方。需要注意的是backgroundTimeRemaining只在进入后台是有效,前台的话会是一个很大的值

@property(nonatomic,readonly) NSTimeInterval backgroundTimeRemaining NS_AVAILABLE_IOS(4_0);

方式二:系统托管下载任务(NSURLSession)

待补充

参考: