objc系列译文(5.5):iOS7的多任务处理

447 查看

在iOS7之前,当程序退出后,开发者对程序几乎做不了什么。除了VOIP和基于位置的特性,唯一能够在后台运行代码的途径只有使用后台任务(background tasks),但后台任务只会执行几分钟。如果你想要下载一部很大的视频以便离线观看,或者将用户图片备份到服务器,你只能完成部分的任务。

ios7新添加了两个可以在后台更新应用程序界面和内容的APIs。第一个API是后台获取(Background Fetch),允许你在定期间隔内从网络获取新内容。第二个API是远程通知 (Remote Notification),它是一个新特性,它在当新事件发生时利用推送通知(Push Notifications)去告知程序。这两个新的机制,帮助你保持程序界面最新,还可以在新的后台传输服务(Background Transfer Service)中安排任务,这允许你在进程外执行网络传输(下载和上传)。

后台获取(Background Fetch)和远程通知(Remote Notification)基于简单的应用程序委托钩子,在应用程序挂起之前的30秒时钟时间开始执行工作。它们不是用于CPU频繁工作或者长时间运行任务,而是用来处理长时间运行的网络请求队列,例如下载一部很大的电影,或者执行快速的内容更新。

在用户看来,多任务处理唯一明显的变化就是新的程序切换器(app switcher),它会显示当程序退出前台时每一个程序的界面快照。显示这些快照是有原因的:当完成后台工作时,开发者可以更新程序快照,显示新内容的预览。社交网络,新闻,或者天气的应用程序,可以在用户不打开应用程序的情况下显示最新的内容。接下来我们会展示怎么样更新快照。

后台获取(Background Fetch)

后台获取(Background Fetch)是一种智能的轮询机制,它很适合需要经常更新内容的程序,像社交网络,新闻或天气的程序。为了在用户启动程序前提前触发后台获取,系统会根据用户行为唤醒应用程序。举个例子,如果用户经常在下午1点使用某个应用程序,系统会学习,适应并在使用周期前执行后台获取。为了减少电池使用,后台获取(Background Fetch)会跨应用程序被设备的无线电合并,如果你向系统报告新数据无法获取,iOS会适应并使用此信息避免会继续获取。

开启后台获取的第一步是在info plist文件中的UIBackgroundModes健值指定使用的特性。最简单的途径是在Xcode5的project editor中新的性能标签页中(Capabilities tab)设置,这个标签页包含了后台模式部分,可以方便配置多任务选项。

capabilities-on-bgfetch-1

或者,你可以手动编辑这个健值:

下一步,告诉iOS你希望多久进行一次后台获取:

iOS默认不进行后台获取,所以你需要设置一个时间间隔,否则,你的应用程序永远不行在后台进行获取数据。UIApplicationBackgroundFetchIntervalMinimum这个值要求系统尽可能经常去管理应用程序什么时候会被唤醒,但如果不需要这个值,你应该指定你的时间间隔。例如,一个天气的应用程序,可能只需要几个小时才更新一次,iOS将会在后台获取之间至少等待你指定的时间间隔。

如果你的应用允许用户退出登录,那么就没有获取新数据的需要了,你应该把minimumBackgroundFetchInterval设置为UIApplicationBackgroundFetchIntervalNever,这样可以节省资源。

最后一步是在应用程序委托中实现下列方法:

系统唤醒应用程序后将会执行这个委托方法。需要注意的是,你只有30秒的时间来确定获取的新内容是否可用,然后处理新内容并更新界面。30秒时间应该足够去从网络获取数据和获取界面的缩略图,最多只有30秒。当完成了网络请求和更新界面后,你应该调用完成的处理代码。

完成的处理代码有两个目的。首先,系统会估量你的进程消耗的电量,并根据你传递的UIBackgroundFetchResult 参数记录新数据是否可用。其次,当你调用完成的处理代码时,应用的界面缩略图会被采用,并更新应用程序切换器。当用户在应用间切换时,用户将会看到新内容。这种快照行为的完成代码,在新的多任务处理APIs中,很很常见的。

在实际应用中,你应该将completionHandler 传递到应用程序的子组件,然后在处理完数据和更新界面后调用。

在这里,你可能想知道iOS是如何在应用程序后台运行时获得界面快照的,并且想知道应用程序的生命周期与后台获取之间有什么关系。如果应用程序处于挂起状态,系统会先唤醒应用,然后再调用application: performFetchWithCompletionHandler:。如果应用程序还没有启动,系统将会启动它,然后调用常见的委托方法,包括application: didFinishLaunchingWithOptions:。你可以把这种应用程序运行的方式想像为用户从Springboard启动这个程序,区别仅仅在于界面是看不见的,在屏幕外渲染的。

大多数情况下,无论应用在后台启动或者在前台,你会执行相同的工作,但你可以通过查看UIApplication的applicationState属性来判断应用是不是从后台启动。

测试后台获取(Testing Background Fetch)

有两种可以模拟后台获取的途径。最简单是从Xcode运行你的应用,当应用运行时,在Xcode的Debug菜单选择Simulate Background Fetch.

第二种方法,使用scheme更改Xcode运行程序的方式。在Xcode菜单的Product选项,选择Scheme然后选择Manage Schemes.在这里,你可以编辑或者添加一个新的scheme,然后选中Launch due to a background fetch event。如下图:

edit-scheme-simulate-background-fetch

远程通知(Remote Notifications)

远程通知允许你在重要事件发生时,告知你的应用。你可能需要发送新的即时信息,突发新闻的提醒,或者用户喜爱电视的最新剧集已经可以下载以便离线观看的消息。远程通知很适合偶尔出现,但当前很重要的内容,这在后台获取之间出现的延迟是不允许的。远程通知会比后台获取更有效率,因为应用程序只有在需要的时候才会启动。

一条远程通知实际上只是一条普通的带有content-available标志的推送通知。当你在后台更新界面时,你可以发送一条带有提醒信息的推送去告诉用户。但远程通知可以做到在安静地,没有提醒消息或者任何声音的情况下,只去更新应用界面或者触发后台工作。然后你可以在完成下载或者处理完新内容后,发送一条本地通知。

静默的推送通知有速度限制,所以你可以勇敢地根据应用程序的需要发送通知。iOS和苹果推送服务会控制推送通知多久被递送,发送很多推送通知是没有问题的。如果你的推送通知被禁止,推送通知可能会被延迟,直到设备下次发送保持活动状态的数据包,或者收到另外一个通知。7之前,当程序退出后,开发者对程序几乎做不了什么。除了VOIP和基于位置的特性,唯一能够在后台运行代码的途径只有使用后台任务(background tasks),但后台任务只会执行几分钟。如果你想要下载一部很大的视频以便离线观看,或者将用户图片备份到服务器,你只能完成部分的任务。

ios7新添加了两个可以在后台更新应用程序界面和内容的APIs。第一个API是后台获取(Background Fetch),允许你在定期间隔内从网络获取新内容。第二个API是远程通知 (Remote Notification),它是一个新特性,它在当新事件发生时利用推送通知(Push Notifications)去告知程序。这两个新的机制,帮助你保持程序界面最新,还可以在新的后台传输服务(Background Transfer Service)中安排任务,这允许你在进程外执行网络传输(下载和上传)。

后台获取(Background Fetch)和远程通知(Remote Notification)基于简单的应用程序委托钩子,在应用程序挂起之前的30秒时钟时间开始执行工作。它们不是用于CPU频繁工作或者长时间运行任务,而是用来处理长时间运行的网络请求队列,例如下载一部很大的电影,或者执行快速的内容更新。

在用户看来,多任务处理唯一明显的变化就是新的程序切换器(app switcher),它会显示当程序退出前台时每一个程序的界面快照。显示这些快照是有原因的:当完成后台工作时,开发者可以更新程序快照,显示新内容的预览。社交网络,新闻,或者天气的应用程序,可以在用户不打开应用程序的情况下显示最新的内容。接下来我们会展示怎么样更新快照。

后台获取(Background Fetch)

后台获取(Background Fetch)是一种智能的轮询机制,它很适合需要经常更新内容的程序,像社交网络,新闻或天气的程序。为了在用户启动程序前提前触发后台获取,系统会根据用户行为唤醒应用程序。举个例子,如果用户经常在下午1点使用某个应用程序,系统会学习,适应并在使用周期前执行后台获取。为了减少电池使用,后台获取(Background Fetch)会跨应用程序被设备的无线电合并,如果你向系统报告新数据无法获取,iOS会适应并使用此信息避免会继续获取。

开启后台获取的第一步是在info plist文件中的UIBackgroundModes健值指定使用的特性。最简单的途径是在Xcode5的project editor中新的性能标签页中(Capabilities tab)设置,这个标签页包含了后台模式部分,可以方便配置多任务选项。

capabilities-on-bgfetch-1

或者,你可以手动编辑这个健值:

下一步,告诉iOS你希望多久进行一次后台获取:

iOS默认不进行后台获取,所以你需要设置一个时间间隔,否则,你的应用程序永远不行在后台进行获取数据。UIApplicationBackgroundFetchIntervalMinimum这个值要求系统尽可能经常去管理应用程序什么时候会被唤醒,但如果不需要这个值,你应该指定你的时间间隔。例如,一个天气的应用程序,可能只需要几个小时才更新一次,iOS将会在后台获取之间至少等待你指定的时间间隔。

如果你的应用允许用户退出登录,那么就没有获取新数据的需要了,你应该把minimumBackgroundFetchInterval设置为UIApplicationBackgroundFetchIntervalNever,这样可以节省资源。

最后一步是在应用程序委托中实现下列方法:

系统唤醒应用程序后将会执行这个委托方法。需要注意的是,你只有30秒的时间来确定获取的新内容是否可用,然后处理新内容并更新界面。30秒时间应该足够去从网络获取数据和获取界面的缩略图,最多只有30秒。当完成了网络请求和更新界面后,你应该调用完成的处理代码。

完成的处理代码有两个目的。首先,系统会估量你的进程消耗的电量,并根据你传递的UIBackgroundFetchResult 参数记录新数据是否可用。其次,当你调用完成的处理代码时,应用的界面缩略图会被采用,并更新应用程序切换器。当用户在应用间切换时,用户将会看到新内容。这种快照行为的完成代码,在新的多任务处理APIs中,很很常见的。

在实际应用中,你应该将completionHandler 传递到应用程序的子组件,然后在处理完数据和更新界面后调用。

在这里,你可能想知道iOS是如何在应用程序后台运行时获得界面快照的,并且想知道应用程序的生命周期与后台获取之间有什么关系。如果应用程序处于挂起状态,系统会先唤醒应用,然后再调用application: performFetchWithCompletionHandler:。如果应用程序还没有启动,系统将会启动它,然后调用常见的委托方法,包括application: didFinishLaunchingWithOptions:。你可以把这种应用程序运行的方式想像为用户从Springboard启动这个程序,区别仅仅在于界面是看不见的,在屏幕外渲染的。

大多数情况下,无论应用在后台启动或者在前台,你会执行相同的工作,但你可以通过查看UIApplication的applicationState属性来判断应用是不是从后台启动。

测试后台获取(Testing Background Fetch)

有两种可以模拟后台获取的途径。最简单是从Xcode运行你的应用,当应用运行时,在Xcode的Debug菜单选择Simulate Background Fetch.

第二种方法,使用scheme更改Xcode运行程序的方式。在Xcode菜单的Product选项,选择Scheme然后选择Manage Schemes.在这里,你可以编辑或者添加一个新的scheme,然后选中