iOS 后台任务

iOS提供了以下多中方式处理后台任务

  1. beginBackgroundTaskWithExpirationHandler
  2. 特定任务的后台处理
  3. 后台获取
  4. 推送唤醒
  5. 后台传输

beginBackgroundTaskWithExpirationHandler

1
2
3
4
5
6
7
8
9
10
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
_count = 0;
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(function) userInfo:nil repeats:YES];
return YES;
}
-(void)function {
_count++;
NSLog(@"function:%d",_count);
}

上面代码开启了一个定时器,每隔一秒输出count的值,但当我们的应用退到前台后定时器停止运行,我们可以通过函数beginBackgroundTaskWithExpirationHandler向系统请求更多地时间运行我们的代码,这个”更多的时间”经过测试大概在3分钟左右。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
_count = 0;
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(function) userInfo:nil repeats:YES];
return YES;
}
-(void)function {
_count++;
NSLog(@"function:%d",_count);
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
_identifier = [application beginBackgroundTaskWithExpirationHandler:^{
[application endBackgroundTask:_identifier];
_identifier = UIBackgroundTaskInvalid;
}];
}

_identifier是整型变量,beginBackgroundTaskWithExpirationHandler设置了一个超时回调函数,当超过3分钟后后台任务将被挂起同时执行超时函数,我们应该在超时函数中调用endBackgroundTask,下面代码展示了beginBackgroundTaskWithExpirationHandler更一般的调用方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- (void)beginBackgroundTask {
UIApplication *application = [UIApplication sharedApplication];
_identifier = [application beginBackgroundTaskWithExpirationHandler:^{
[self endBackgroundTask];
}];
}

- (void)endBackgroundTask {
UIApplication *application = [UIApplication sharedApplication];
[application endBackgroundTask:_identifier];
_identifier = UIBackgroundTaskInvalid;
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
[self beginBackgroundTask];
//后台任务
do something;
[self endBackgroundTask];
}

后台获取

后台获取是iOS7新增内容,它的核心作用是设定一个间隔,然后每隔一段时间唤醒应用处理相应地任务,比如我们使用的社交软件,可以每个一定时间获取最新的信息,这样下次我们进入后就不需要等待刷新,使用后台获取的步骤如下:

  1. 添加应用对后台获取的支持,可以在plist文件中修改UIBackgroundMode一项,增加fetch,或者在应用信息的capabilities->background modes中勾选background fetch
  2. 设置最小后台获取时间间隔
  3. 实现application:performFetchWithCompletionHandler
1
2
3
4
5
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[application setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
return YES;
}

如果不设置的话默认为UIApplicationBackgroundFetchIntervalNever,表示不获取,而且这个值代表”最小”后台获取时间间隔,这里所指定的时间间隔只是代表了“在上一次获取或者关闭应用之后,在这一段时间内一定不会去做后台获取”,IOS并不会为了每一个应用频频唤醒CPU,具体唤醒时间得看系统调度,设置为UIApplicationBackgroundFetchIntervalMinimum表示尽可能的对我们的应用进行后台唤醒,这样设置的缺点是耗电。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://blog.csdn.net/youshaoduo/article/details/79063224"]];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"%@",[error localizedDescription]);
completionHandler(UIBackgroundFetchResultFailed);
} else {
////更新UI
NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
completionHandler(UIBackgroundFetchResultNewData);
}
}];
[task resume];
}

与beginBackgroundTaskWithExpirationHandler相似,系统提供了回调completionHandler,用于通知系统任务执行完毕。

推送唤醒

  1. 在UIBackgroundModes添加remote-notification
  2. 更改推送的payload:需要在payload中添加content-available,并设置为1
  3. 实现推送唤醒代码
    1
    -(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{}

代码实现与上一种方式一致,任务实现完需要调用回调方法通知系统

文章目录
  1. 1. beginBackgroundTaskWithExpirationHandler
  2. 2. 后台获取
  3. 3. 推送唤醒
|