天天品尝iOS7甜点 :: Day 3 :: Background Fetch

这篇文章是天天品尝iOS7甜点系列的一部分,你可以查看完整的系列目录:天天品尝iOS7甜点


介绍

iOS7介绍了一个新的多任务APIs - 之前我们介绍了运用NSURLSession进行后台数据传输,不管你的app是否处与运行状态中。另外一个新的API特性是后台提取,它可以让app进行更新内容,不管app是否正在运行。这样就可以使你的app在第二次打开的时候就已经更好好了内容,iOS可以很智能的更绝你app使用情况进行后台提取工作,并且可以节省电池寿命。例如它可以注意到你每天醒来就会上社交网络,所以它就会事先自己提取好你想要的信息。

完成的代码已经在github可供下载使用:github.com/ShinobiControls/iOS7-day-by-day

Enabling background fetch - 开启后台提取功能

如果app希望注册使用后台提取功能,你可以在Xcode5的capabilities页签中设置,并且非常的简单:

还有一件事情需要做的就是,你需要指定后台提取功能运行的频率,如果你知道你的数据每一个小时都要上传一次,则可以自己设置提取功能的时间。如果你不知道的话,那么就使用默认推荐的值:

1
2
3
4
5
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Set the fetch interval so that it is actually called
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
return YES;
}

注意这里minimumBackgroundFetchInterval的默认值是UIApplicationBackgroundFetchIntervalNever,所以这样你的应用程序会进行调用设置.

Implementation - 实现

如果后台提取发生了,iOS就会开启app并且调用应用程序的代理方法application:performFetchWithCompletionHandler:,然后应用程序就会有一定的时间来执行提取功能并调用提供的块程序。

本篇文章的实例程序是一个交通状态的app,它可以模拟接受到的不同路段的交通信息,然后展示到UITableView上面,在演示程序中,更新是随机生成的,并且可以通过下拉表格进行更新数据,对应的处理接口方法为:

1
2
3
4
5
- (void)refreshStatus:(id)sender {
[self createNewStatusUpdatesWithMin:0 max:3 completionBlock:^{
[refreshControl endRefreshing];
}];
}

下面是工具方法createNewStatusUpdatesWithMin:max:completionBlocl::

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- (NSUInteger)createNewStatusUpdatesWithMin:(NSUInteger)min max:(NSUInteger)max completionBlock:(SCTrafficStatusCreationComplete)completionHandler {
NSUInteger numberToCreate = arc4random_uniform(max-min) + min;
NSMutableArray *indexPathsToUpdate = [NSMutableArray array];

for (int i = 0; i < numberToCreate; i++) {
[self.trafficStatusUpdates insertObject:[SCTrafficStatus randomStatus] atIndex:0];
[indexPathsToUpdate addObject:[NSIndexPath indexPathForRow:i inSection:0]];
}

[self.tableView insertRowsAtIndexPaths:indexPathsToUpdate withRowAnimation:UITableViewRowAnimationFade];

if (completionHandler) {
completionHandler();
}

return numberToCreate;
}

在这里我们创建了一个随机数来随机的更新,然后我们更新数据,更新表格视图,这是标准的UITableView代码,在实际情况下,就可以根据网络请求的数据进行更新。

为了能够创建后台提取的功能,我们需要在我们的view controller中添加一个使用API的方法:

1
2
3
4
5
6
7
8
9
10
11
12
- (NSUInteger)insertStatusObjectsForFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
NSUInteger numberCreated = [self createNewStatusUpdatesWithMin:0 max:3 completionBlock:NULL];

NSLog(@"Background fetch completed - %d new updates", numberCreated);

UIBackgroundFetchResult result = UIBackgroundFetchResultNoData;
if (numberCreated > 0) {
result = UIBackgroundFetchResultNewData;
}
completionHandler(result);
return numberCreated;
}

在app的background fetch代理方法中调用上述方法,所以,我们可以过会来调用这个方法。首先,我们需要创建一些更新,当更新结束的时候再次回调background fetch的handler程序。

最后,我们需要与app的delegate方面相关联:

1
2
3
4
5
6
7
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
// Get hold of the view controller
SCViewController *vc = (SCViewController *)self.window.rootViewController;
// Insert status updates and pass in the completion handler block
NSUInteger numberInserted = [vc insertStatusObjectsForFetchWithCompletionHandler:completionHandler];
[UIApplication sharedApplication].applicationIconBadgeNumber += numberInserted;
}

现在,当程序唤醒后台提取的功能,它就是进入view controller中执行更新操作。

Testing - 测试

到目前为止,我们还没有测试程序,并且也没有明确的说明如何模拟后台提取事件,Xcode5已经为我们考虑到了,但是在我们深入之前我们需要考虑两种情况:

1.App currently runing in background - app当前在后台运行

用户开启了程序,然后离开程序去做别的事情,这种情况下,程序会在后台继续的运行(进程并没有被杀死),Xcode提供了一个新的调试方法来模拟这种情况,所以测试就变得和运行程序一样的简单了,点击Home键,然后执行新的调试方法:

同时进行后台提取的时候最后能够打印一些日志,进行查看。在我们的简单程序中,每一次的后台提取都是修改程序的标记数字.

2.App currently in terminated state - app当前已经终止进程

应用程序运行之后,进程被杀死了,不管是自己手动杀死的还是iOS操作系统杀死的。为了模拟这样的情况简单的方法就是在Xcode中添加一个新的scheme。进入manage schemes管理页面,然后复制一个已经存在的scheme,编辑新建的scheme,选中run task中的options页签中的launch due to a background fetch event.

现在,当你运行这个新建的scheme的时候,你将会看到模拟器启动了,但是app并没有启动。如果你在background fetch中打印了日志信息,你就会看到有日志输出。

总结

后台提取功能,可以让你的程序用户体验效果更加的好,如果你的应用是基于互联网数据更新,那么这非常简单的方法,让应用程序时刻获得最新的信息。

本文翻译自:iOS7 Day-by-Day :: Day 3 :: Background Fetch

文章目录
  1. 1. 介绍
  2. 2. Enabling background fetch - 开启后台提取功能
  3. 3. Implementation - 实现
  4. 4. Testing - 测试
    1. 4.0.1. 1.App currently runing in background - app当前在后台运行
    2. 4.0.2. 2.App currently in terminated state - app当前已经终止进程
  • 5. 总结
  • ,