iOS应用后台任务的三两事

翻译自《App Programming Guide for iOS--Background Execution》

当用户将运行App切换到后台时,系统会更改其运行状态。对大多数的应用
后台状态就是切换为挂起状态(suspended)。挂起应用是提升电池寿命的一种方式,同时系统也会投入更多的系统资源给用户当前正使用的应用。

大多数的应用可以轻易的切换为挂起状态(suspended),但是有些应用因为自身需求的原因会在后台保持运行。一个关于远足的App也许会一直追踪用户的位置,从而可以在地图上展示运动的轨迹。一个音频App也许需要在锁屏后继续播放音乐。其他的一些应用希望在后台下载内容,这样可以缩减给用户展示的时间。当前你需要让你的App保持后台运行,iOS系统会给你有效的帮助,从而不会过度消耗系统资源和电量。这项技术的实现分为以下三种情况:

  • 在前台开启了短任务的应用在进入后台时可以请求一段后台运行时间去完成任务。
  • 在前台开始下载任务的应用可以下载任务的控制移交给系统,从而在后台任务运行期间可以控制应用的挂起或终止。
  • 对于需要在后台运行特殊类型任务的应用可以声明一种或多种后台运行的模式

除非后台任务可以整体提升用户的体验性,否则尽量避免运行后台任务。应用进入后台也许是由于用户切换了另一个App或者锁屏了,所以临时不使用了。以上任一情况都表明了目前用户不需要维持后台任务了。如果依然维持后台任务将会消耗手机的电量,而且用户也会手动关闭应用。因此尽量考虑好是否需要后台任务,尽量避免后台任务运行。


Executing Finite-Length Tasks 执行限定时间的任务

应用切换到后台时,期望尽快停止运行任务,因此可以被系统挂起。如果前台任务在运行中,则需要额外的时间去完成。你可以调用UIApplication的方法 beginBackgroundTaskWithName:expirationHandler:或者 beginBackgroundTaskWithExpirationHandler:去申请一些额外的运行时间。调用任一方法都会暂时地延迟应用的暂停,提供额外的时间完成任务。完成后台运行的工作时,App可以调用方法endBackgroundTask:通知系统后台任务已完成可以挂起(suspended)。

每次调用方法 beginBackgroundTaskWithName:expirationHandler:或者 beginBackgroundTaskWithExpirationHandler:都会生成一个关联相关任务的唯一token。当你的应用完成一个任务时,必须调用方法endBackgroundTask :且传入生成的token,让系统知道任务已经完成了。调用endBackgroundTask :失败会导致结束应用的运行。如果开始任务前你提供了过期处理器,系统会调用这个处理器给你一个机会去结束后台任务,从而避免应用被终止。
You can even follow this pattern while your app is executing in the foreground.

你不需要等到应用进入后台时再指派后台任务。更有用的设计方式是在开始任务前调用方法 beginBackgroundTaskWithName:expirationHandler:或者 beginBackgroundTaskWithExpirationHandler:,任务一旦技术就调用endBackgroundTask:。即使你的应用在前台运行也可以遵循这种模式。

列表3-1展示了长时间运行任务如何过渡到后台运行。此例子中,请求后台任务方式包含了一个过期处理器,以防止任务会执行太长的时间。这个任务本身被放置到一个异步调度的队列中,因此applicationDidEnterBackground:可以正常的执行返回。

Listing 3-1 进入后台时开启后台任务

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    bgTask = [application beginBackgroundTaskWithName:@"MyTask" expirationHandler:^{
        // Clean up any unfinished task business by marking where you
        // stopped or ending the task outright.
        [application endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    }];
 
    // Start the long-running task and return immediately.
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
 
        // Do the work associated with the task, preferably in chunks.
 
        [application endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    });
}

注意:开始一个任务时尽量提供一个过期处理器,如果你想知道你的应用在后天还剩余多少运行时间,可以从UIApplicationbackgroundTimeRemaining的属性中获取。

在过期处理器(expiration handlers)里可以包含需要关闭任务的代码,然而这里面一定不要放执行耗时的代码,因为调用过期处理器时你的应用已经到达运行极限了,执行耗时代码也许会终止应用,基于这个原因,只执行一个轻量的状态清除和任务结束代码。


Downloading Content in the Background 后台下载任务


Implementing Long-Running Tasks 执行长时间运行的任务

Declaring Your App’s Supported Background Tasks

Tracking the User’s Location

Playing and Recording Background Audio

Implementing a VoIP App

Fetching Small Amounts of Content Opportunistically

Using Push Notifications to Initiate a Download

Downloading Newsstand Content in the Background

Communicating with an External Accessory

Communicating with a Bluetooth Accessory


Getting the User’s Attention While in the Background


Understanding When Your App Gets Launched into the Background


Being a Responsible Background App


Opting Out of Background Execution 选择退出后台执行

如果你一点也不想让你的应用在后台执行,你可以显示地在info.plist中添加keyUIApplicationExitsOnSuspend(并且设置成YES)。When an app opts out, it cycles between the not-running, inactive, and active states and never enters the background or suspended states. 当用户按下home键退出应用时,应用的代理方法applicationWillTerminate:被调用,并且在应用终止前有大约5s的时间去清理工作。
强烈不推荐选择退出后台执行,但是某些情况下也许偏向于使用这种选择。尤其是,如果编写后台执行代码会显著增加复杂性,结束应用也许是一种简便的方式。同样,如果你的app消耗了大量的内存并且很难释放,系统也许无论如何都会杀死你的应用以保证其他的应用正常运行。选择结束程序替代切换到后台也许会得到相同的结果,同时还能节省你的开发时间和精力。

For more information about the keys you can include in your app’s Info.plist file, see Information Property List Key Reference.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353

推荐阅读更多精彩内容