App Programming Guide for iOS -> 处理应用状态转换的策略(二)

当应用进入前台的时候该做什么

回到前台的过程是应用重启一些任务的机会,这些任务是在应用进入后台的时候被停止的。图4-4展示了应用进入前台时所经历的步骤。applicationWillEnterForeground:方法应该撤销在 applicationDidEnterBackground:方法中的操作,并在applicationDidBecomeActive:方法中继续执行与应用启动时一样的任务。

图4-4 从后台转换到前台

注意:UIApplicationWillEnterForegroundNotification通知也可用于跟踪应用是否重新进入前台。应用的对象可以使用默认通知中心来注册这个通知。

准备处理通知队列

当一个应用从挂起状态返回到前台或者后台状态的时候,它都必须为处理通知队列做好准备。一个挂起状态的应用,不能执行任何代码,所以也不能处理相关的通知,包括方向改变、时间改变、偏好改变、以及很多影响应用外观和状态改变的通知。为了确保这些改变没有丢失,系统会把很多相关的通知组成队列,一旦应用再次执行代码的时候(无论是前台还时后台),把它们发送给应用。为了防止应用在恢复的时候因为通知太多而导致负荷超载,系统会将事件合并成一个通知并发送给应用。这个通知反映了从应用被挂以来的净更改。

表4-1 罗列了可以合并且发送到应用的通知。这些通知的大多数都可以直接发送给已注册的观察者。但有一些,例如与设备方向更改相关的,通常会被系统框架截取,并以另一种方式发送给应用。

表4-1 被发送到苏醒应用的通知

事件 通知
连接或断开配件 EAAccessoryDidConnectNotification
EAAccessoryDidDisconnectNotification
设备方向改变 UIDeviceOrientationDidChangeNotification
除了此通知外,视图控制器可以自动的更新它们的界面方向。
显著的时间变化 UIApplicationSignificantTimeChangeNotification
电池电量或者电池状态改变 UIDeviceBatteryLevelDidChangeNotification
UIDeviceBatteryStateDidChangeNotification
接近状态已改变 UIDeviceProximityStateDidChangeNotification
受保护文件状态已改变 UIApplicationProtectedDataWillBecomeUnavailable
UIApplicationProtectedDataDidBecomeAvailable
连接或断开外接显示器 UIScreenDidConnectNotification
UIScreenDidDisconnectNotification
显示屏的画面模式已改变 UIScreenModeDidChangeNotification
通过Settings应用修改了首选项 NSUserDefaultsDidChangeNotification
当前语言或地区设置已改变 NSCurrentLocaleDidChangeNotification
用户iCloud账户状态已改变 NSUbiquityIdentityDidChangeNotification

通知队列会发送到应用的主运行循环,通常会先于触摸事件和用户输入发送。大多数应用都能快速处理这些事件,不会造成明显的延迟。但是,如果应用出现从后台返回时过于缓慢的情况,请使用Instruments来确定是否是由处理通知的代码导致的。

返回到前台的应用,也可接收更新视图的通知。运行在后台的应用仍可以调用setNeedsDisplay 或 setNeedsDisplayInRect:方法来请求更新视图。但是,因为这些视图不可见,系统会合并这些请求,等到应用会到前台之后再对它们进行更新。

处理iCloud的改变

无论何种原因使得iCloud状态改变,系统都会向应用发送一个NSUbiquityIdentityDidChangeNotification通知。当用户登录或退出iCloud账户,或允许或禁止同步文档和数据时,iCloud状态都会发生改变。这个通知是应用暗示要更新缓存以及任何和iCloud相关的用户界面元素,以适应状态的改变。例如,当用户注销iCloud的时候,你应该删除所有基于iCloud的文件或数据的引用。

如果应用已经提醒过用户是否存储文件到iCloud,那么在iCloud状态改变的时候就不再重复提醒。在第一次提醒用户之后,在应用的本地偏好中存储用户的选择。然后你可以使用Settings束或者应用中的选项来显示该偏好。但是不要再次提醒,除非该偏好当前不在用户默认的数据库中。

处理区域(locale)改变

如果用户在挂起期间改变了所在区域,那么当应用回到前台的时候,你能使用NSCurrentLocaleDidChangeNotification通知来对任何包含区域敏感信息的视图进行更新,例如日期、时间、数字。当然,避免区域相关问题的最好办法是编写代码来让更新视图更容易。例如:

  • 当要取回NSLocale对象的时候,使用autoupdatingCurrentLocale类方法。该方法返回一个区域对象,它会根据区域改变而自动更新自身,因此你无需重新创建它。然而,当区域改变时,你仍然需要刷新含有区域派生信息的界面。
  • 一旦当前的区域信息发生改变,就应该重新创建任何缓存的数据及数字格式化对象。

更多关于国际化你的代码以便处理区域改变的信息,参见Internationalization and Localization Guide。

处理应用设置的更改

如果应用由通过Settings应用管理的设置时,应用应该观察NSUserDefaultsDidChangeNotification通知。因为用户可以在应用挂起或者后台期间改变设置,你能使用这个通知来回应这些设置中的重要更改。在某些情况下,响应这个通知能帮助关闭潜在的安全漏洞。例如,email程序应该响应用户账户信息的改变。未对这些更改进行检测,会导致隐私和安全方面的问题。具体来说,当前用户可以使用旧的账户信息发送邮件,即使该账户不再属于该用户。

在收到NSUserDefaultsDidChangeNotification通知后,应用应该重新加载相关的设置,如有必要,重新设置它的用户界面。如果密码或其他安全相关的信息改变了,你还应该隐藏之前显示的信息,并强制用户输入新密码。

当应用进入后台时该做什么

当应用从前台进入后台执行时,使用applicationDidEnterBackground:方法来执行以下操作:

  • 准备获取应用的图片。当applicationDidEnterBackground:方法返回时,系统的到一张应用用户界面的图片,并将这张图片用于转场动画。如果视图中包含任何敏感信息,你应该在applicationDidEnterBackground: 返回之前隐藏或修改这些界面。如果作为这个处理的一部分,你添加一个新视图到视图层次结构中,你必须强制这些视图自我绘制,如Prepare for the App Snapshot中所述那样。
  • 保存所有相关的应用状态信息。在进入后台之前,应用应该已经保存了所有关键用户数据。使用这个到后台的过渡期,保存应用的最后状态。
  • 根据需要释放内存。释放任何你不需要的缓存数据,并尽量清理以减少应用的内存占用。占用大量内存的应用会被系统首先终止,所以要释放图像资源、数据缓存、以及其他你不再需要的对象。更多信息,参见Reduce Your Memory Footprint。

应用委托方法applicationDidEnterBackground:大概有5秒钟来完成这些任务并返回。实际上,这些方法应该尽可能块的返回,如果方法超过时间也没有返回,应用会被杀死并清除出内存。如果你仍需要更多时间来执行任务,调用beginBackgroundTaskWithExpirationHandler:方法来请求后台执行时间,然后在辅助线程开始长时运行任务。无论你是否开启后台任务, applicationDidEnterBackground:方法仍将在5秒钟内退出。

注意:除了调用 applicationDidEnterBackground: 方法,系统还发送UIApplicationDidEnterBackgroundNotification通知。你可以使用这个通知来把清理任务分发到应用中的其他对象。

基于应用的功能,在进入后台的时候,应用还要做一些事情。例如,任何活跃的Bonjour服务应该被挂起,停止调用OpenGL ES函数。当进入后台时应该执行的操作的列表,参见Being a Responsible Background App。

后台转换周期

当用户点击Home键、按下休眠/唤醒按钮、或者系统启动其他应用,前台的应用会转换到非活跃状态,然后进入后台状态。这些转换导致调用应用委托的applicationWillResignActive:和applicationDidEnterBackground:方法,如图4-5所示。在从applicationDidEnterBackground:方法返回之后,大多数应用很快进入到挂起状态。请求特定后台任务(如播放音乐)或从系统请求额外运行时间的应用可以继续运行一段时间。

图4-5 从前台进入后台

准备应用快照

在应用委托方法applicationDidEnterBackground:返回不久,系统会得到一张应用视窗的快照。同样,当应用被唤醒来执行后台任务的时候,系统可以可以得到一张新的快照,新快照反映了相关的改变。例如,当应用被唤醒来处理下载项目时,系统会得到新快照,以便能够反映因为合并项目而导致的任何变化。系统在多任务UI中使用这些快照来展示应用的状态。

如果在进入后台之前你改变了视图,你可以调用主视图的snapshotViewAfterScreenUpdates:方法来强制执行这些更改。在视图上调用setNeedsDisplay方法对快照无效,因为在下一个绘图周期之前快照已产生,因此可以防止任何改变被渲染。调用使用值为YES的snapshotViewAfterScreenUpdates:方法,立即更新快照使用的底层缓冲区。

减少内存占用

每个应用都应该在进入后台之前尽可能多的释放内存。系统会在内存中保留尽可能多的内存,但是当内存不足时,它会挂起应用以便回收内存。那些在后台消耗大量内存的应用会被先终止。

实际上,应用一旦不需要某个对象时,就应该移除对该对象的强引用。移除强引用可以让编译器获得释放这些对象的能力,以便可以回收相应的内存。但是,如果你想缓存一些对象以提高性能,你可以在进入后台之前保留它们。

一些应该尽可能移除强引用的对象:

  • 你创建的图片对象。(一些返回图片的UIImage 方法,它底层的图片数据会被系统自动清除。更多信息,参见UIImage Class Reference的浏览讨论。)
  • 可以从磁盘再次加载的媒体或数据文件。
  • 任何不再需要且创建方便的对象。

为了帮助减少应用对内存的占用,系统会在应用进入后台前自动清除一些它代表应用分配的数据。

  • 系统清除所有Core Animation层的备份。此功能不会从内存移除应用的图层对象,不会改变现有图层属性。它只是防止这些显示在屏幕上的内容,在后台时仍试图作用于应用。
  • 移除任何对缓存图片的系统引用。
  • 移除对其他系统管理的数据缓存的强引用,

(本节结束)

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

推荐阅读更多精彩内容