實施特定應(yīng)用功能的策略
不同的應(yīng)用程序有不同的需求凫岖,但是一些是在許多類型的應(yīng)用程序常見的行為支救,以下部分提供有關(guān)如何在應(yīng)用程序中實現(xiàn)特定類型的功能的指導(dǎo)幢泼。
隱私策略
在設(shè)計應(yīng)用程序時渡嚣,保護(hù)用戶的隱私是重要的考慮因素渣淳。隱私保護(hù)包括保護(hù)用戶的數(shù)據(jù)脾还,包括用戶的身份和個人信息。系統(tǒng)框架已經(jīng)提供隱私控制來管理諸如聯(lián)系人之類的數(shù)據(jù)入愧,但是您的應(yīng)用程序應(yīng)該采取措施保護(hù)您在本地使用的數(shù)據(jù)鄙漏。
使用磁盤加密保護(hù)數(shù)據(jù)
數(shù)據(jù)保護(hù)使用內(nèi)置硬件以磁盤上的加密格式存儲文件嗤谚,并根據(jù)需要進(jìn)行解密。當(dāng)用戶的設(shè)備被鎖定時怔蚌,受保護(hù)的文件是無法訪問的巩步,甚至是創(chuàng)建它們的應(yīng)用程序。在應(yīng)用程序可以訪問其受保護(hù)的文件之前媚创,用戶必須解鎖設(shè)備(通過輸入相應(yīng)的密碼)渗钉。
大多數(shù)iOS設(shè)備都提供數(shù)據(jù)保護(hù),并符合以下要求:
用戶設(shè)備上的文件系統(tǒng)必須支持?jǐn)?shù)據(jù)保護(hù)钞钙。大多數(shù)設(shè)備支持此行為。
用戶必須為設(shè)備設(shè)置一個活動的密碼鎖芒炼。
要保護(hù)文件,請向文件添加一個屬性鲸湃,指示所需的保護(hù)級別。使用NSData類或NSFileManager類添加此屬性暗挑。編寫新文件時斜友,可以使用具有相應(yīng)保護(hù)值的writeDataFile:options:NSData的error:method作為寫入選項之一。對于現(xiàn)有文件鲜屏,可以使用NSFileManager的setAttributes:ofItemAtPath:error:method來設(shè)置或更改NSFileProtectionKey的值。使用這些方法時洛史,請為文件指定以下保護(hù)級別之一:
無保護(hù) - 文件已加密惯殊,但不受密碼保護(hù),并在設(shè)備鎖定時可用也殖。指定NSDataWritingFileProtectionNone選項(NSData)或NSFileProtectionNone屬性(NSFileManager)土思。
完成 - 設(shè)備被鎖定時,文件被加密并且不可訪問忆嗜。指定NSDataWritingFileProtectionComplete選項(NSData)或NSFileProtectionComplete屬性(NSFileManager)己儒。
完成,除非已經(jīng)打開 - 文件已加密霎褐。當(dāng)設(shè)備被鎖定時,無法訪問關(guān)閉的文件该镣。用戶解鎖設(shè)備后冻璃,您的應(yīng)用程序可以打開該文件并使用該文件。如果用戶在文件打開時鎖定設(shè)備,您的應(yīng)用程序可以繼續(xù)訪問它省艳。指定NSDataWritingFileProtectionCompleteUnlessOpen選項(NSData)或NSFileProtectionCompleteUnlessOpen屬性(NSFileManager)娘纷。
完成,直到第一次登錄 - 文件被加密跋炕,無法訪問赖晶,直到設(shè)備啟動并且用戶已解鎖一次。指定NSDataWritingFileProtectionCompleteUntilFirstUserAuthentication選項(NSData)或NSFileProtectionCompleteUntilFirstUserAuthentication屬性(NSFileManager)辐烂。
如果您保護(hù)文件遏插,您的應(yīng)用程序必須準(zhǔn)備好丟失對該文件的訪問。啟用完整的文件保護(hù)后纠修,當(dāng)用戶鎖定設(shè)備時胳嘲,您的應(yīng)用程序?qū)⑹プx取和寫入文件內(nèi)容的能力。您可以使用以下技術(shù)之一跟蹤對受保護(hù)文件狀態(tài)的更改:
應(yīng)用程序委托可以實現(xiàn)applicationProtectedDataWillBecomeUnavailable:和applicationProtectedDataDidBecomeAvailable:methods扣草。
任何對象都可以注冊UIApplicationProtectedDataWillBecomeUnavailable和UIApplicationProtectedDataDidBecomeAvailable通知了牛。
任何對象都可以檢查共享UIApplication對象的protectedDataAvailable屬性的值,以確定文件當(dāng)前是否可訪問鹰祸。
對于新文件蛙婴,建議您在寫入任何數(shù)據(jù)之前啟用數(shù)據(jù)保護(hù)敬锐。如果使用writeToFile:options:error:方法將NSData對象的內(nèi)容寫入磁盤台夺,則會自動進(jìn)行。對于現(xiàn)有文件颤介,添加數(shù)據(jù)保護(hù)將使用新的受保護(hù)版本替換未受保護(hù)的文件滚朵。
識別您的應(yīng)用程序的唯一用戶
只有在這樣做時辕近,才能識別應(yīng)用程序的用戶移宅,才能為該用戶提供明確的收益漏峰。如果您只需要將應(yīng)用的一個用戶與其他用戶區(qū)分開來倔喂,則iOS提供可幫助您執(zhí)行此操作的標(biāo)識符席噩。但是班挖,如果您需要更高級別的安全性萧芙,您可能需要自己做更多的工作双揪。例如渔期,提供金融服務(wù)的應(yīng)用程序可能希望提示用戶登錄憑據(jù)疯趟,以確保用戶有權(quán)訪問特定帳戶信峻。
重要提示:在識別用戶時,始終要透明了解您獲取的任何信息的意圖踢步。識別用戶是不可接受的丑掺,防止您可以偷偷跟蹤它們兼丰。
以下是一些常見的情況地粪,可能需要您識別用戶蟆技,以及如何實現(xiàn)它們的解決方案质礼。
您希望將用戶鏈接到服務(wù)器上的特定帳戶眶蕉。包括登錄屏幕,要求用戶安全地輸入帳戶信息饭入。通過以加密形式存儲肛真,始終保護(hù)您從用戶收集的帳戶信息乾忱。
您想?yún)^(qū)分不同設(shè)備上運行的應(yīng)用程序的實例窄瘟。使用UIDevice類的identifierForVendor屬性來獲取一個區(qū)分一個設(shè)備上的用戶與其他設(shè)備上的用戶的ID∧ぃ現(xiàn)在新蟆,該技術(shù)可以讓您識別特定的用戶。單個用戶可以具有多個設(shè)備帕翻,每個設(shè)備具有不同的ID值。
您想要為廣告目的識別用戶。使用ASIdentifierManager類的advertisingIdentifier屬性獲取用戶的ID泉蝌。
由于用戶可以在所有iOS設(shè)備上運行應(yīng)用程序勋陪,因此Apple不提供在多個設(shè)備上識別同一用戶的方法诅愚。如果您需要識別特定用戶,則必須使用普遍唯一的ID(UUID)等浊,登錄帳戶或其他類型的身份識別系統(tǒng)提供您自己的解決方案筹燕。
評級限制
用戶可以設(shè)置限制撒踪,指定要在應(yīng)用程序中使用的媒體的評級。如果您的應(yīng)用程序根據(jù)限制播放媒體或修改其行為泵三,則需要確定當(dāng)前設(shè)置并在設(shè)置更改時進(jìn)行響應(yīng)俺抽。
要獲取當(dāng)前設(shè)置,請獲取共享的standardUserDefaults對象冕末,并使用objectForKey:方法查看以下項的值:
媒體評級鍵值
com.apple.content-rating.ExplicitBooksAllowed
布爾档桃。如果此鍵的值為NO,則不允許顯式書籍
com.apple.content-rating.ExplicitMusicPodcastsAllowed
布爾。如果此鍵的值為NO斗幼,則不允許顯示音樂蜕窿,電影和播客毁兆。
com.apple.content-rating.AppRating
的NSNumber气堕。該鍵的值范圍為0到1000.不允許其評級高于當(dāng)前鍵值的應(yīng)用程序。
com.apple.content-rating.MovieRating
的NSNumber畔咧。該鍵的值范圍為0到1000.不允許其分級高于當(dāng)前鍵值的影片茎芭。
com.apple.content-rating.TVShowRating
的NSNumber。該鍵的值范圍為0到1000.不允許其等級高于當(dāng)前鍵值的電視節(jié)目誓沸。
注意:如果objectForKey:為特定鍵返回nil梅桩,則表示有關(guān)此特定限制的信息不可用。在這種情況下拜隧,您的應(yīng)用程序可以使用自己的策略來確定適當(dāng)?shù)脑u級宿百。
要檢測用戶何時更改限制洪添,請注冊通知NSUserDefaultsDidChangeNotification宋光。共享的standardUserDefaults對象在檢測到位于其中一個持久域中的首選項的更改時赘艳,會將此通知發(fā)送到您的應(yīng)用程序旭蠕。
應(yīng)用程序評級是針對我們的國家/地區(qū)代碼定義的旗芬,并被普遍應(yīng)用。表5-1顯示了與每個美國應(yīng)用程序評級相關(guān)聯(lián)的值。
表5-1應(yīng)用程序評分
評分名稱
數(shù)值
4+
100
9+
200
12+
300
17+
600
電影和電視的評分因國家而異定鸟。如果一個國家或地區(qū)沒有為電影或電視節(jié)目指定評級系統(tǒng)季眷,您的應(yīng)用程序應(yīng)使用自己的策略來確定適當(dāng)?shù)脑u級挺峡。雖然大多數(shù)地區(qū)定義電影評級,但只有少數(shù)人定義電視節(jié)目評分暖眼。
區(qū)域可以定義多個評級級別,每個級別與描述評級的名稱和范圍為0到1000的數(shù)字相關(guān)聯(lián)嫩絮。例如,美國使用字符串“G”,數(shù)字100指定最低級別電影評級等級。
即使您的應(yīng)用沒有播放媒體椅您,也可能需要將自己的評分系統(tǒng)映射到電影或電視節(jié)目評分系統(tǒng)马僻。例如溶弟,只有當(dāng)美國電影評級“R”被允許時菜拓,游戲才能啟用某些功能俺夕。要查看當(dāng)前的評分列表劝贸,請下載此文檔的伴隨文件(鏈接位于頁面頂部)。
支持多種版本的iOS
支持最新版本的iOS以及一個或多個早期版本的應(yīng)用程序必須使用運行時檢查來防止在舊版本的iOS上使用較新的API。運行時檢查會阻止您的應(yīng)用程序在嘗試使用當(dāng)前操作系統(tǒng)上不可用的功能時崩潰曾我。
您可以進(jìn)行幾種類型的檢查:
要確定一個類是否存在悦陋,請查看它的Class對象是否為nil踏揣。鏈接器對于任何未知的類對象返回nil捞稿,使得可以使用類似于以下的條件檢查:
if ([UIPrintInteractionController class]) {
// Create an instance of the class anduse it.
}
else {
// The print interaction controller isnot available so use an alternative technique.
}
要確定方法是否可用于現(xiàn)有類,請使用instancesRespondToSelector:class方法或respondToSelector:instance方法拼缝。
要確定基于C的函數(shù)是否可用娱局,請執(zhí)行函數(shù)名為NULL的布爾比較。如果符號不為NULL珍促,則可以調(diào)用該函數(shù)铃辖。例如:
if(UIGraphicsBeginPDFPage!= NULL){
UIGraphicsBeginPDFPage();
}
有關(guān)如何編寫支持多個部署目標(biāo)的代碼的更多信息和示例猪叙,請參閱SDK兼容性指南娇斩。SDK Compatibility Guide
保持你的應(yīng)用程序的視覺外觀Across Launches
即使您的應(yīng)用程序支持后臺執(zhí)行,也不能永久運行穴翩。在某些時候犬第,系統(tǒng)可能需要終止您的應(yīng)用程序以釋放當(dāng)前前臺應(yīng)用程序的內(nèi)存。但是芒帕,用戶不應(yīng)該關(guān)心應(yīng)用程序是否已在運行或終止歉嗓。從用戶的角度來說,退出應(yīng)用程序似乎暫時中斷背蟆。當(dāng)用戶返回到應(yīng)用程序時鉴分,該應(yīng)用程序應(yīng)始終將用戶返回到最后一個使用點,以便用戶可以繼續(xù)執(zhí)行任何正在進(jìn)行的任務(wù)带膀。這種行為為用戶提供了更好的體驗志珍,并且與UIKit內(nèi)置的狀態(tài)恢復(fù)支持相對容易實現(xiàn)。
UIKit中的狀態(tài)保存系統(tǒng)提供了一個簡單但靈活的基礎(chǔ)設(shè)施垛叨,用于保存和恢復(fù)應(yīng)用程序視圖控制器和視圖的狀態(tài)伦糯。基礎(chǔ)設(shè)施的工作是在適當(dāng)?shù)臅r候推動維護(hù)和恢復(fù)過程嗽元。為此敛纲,UIKit需要您的應(yīng)用程序的幫助。只有您了解您的應(yīng)用程序的內(nèi)容剂癌,因此只有您可以編寫保存和還原該內(nèi)容所需的代碼淤翔。當(dāng)您更新應(yīng)用程序的UI時,只有您知道如何將較舊的保留內(nèi)容映射到界面中的較新對象佩谷。
你有三個地方必須在你的應(yīng)用程序中考慮狀態(tài)保存:
您的應(yīng)用程序委托對象旁壮,它管理應(yīng)用程序的頂級狀態(tài)
您的應(yīng)用程序的視圖控制器對象辞做,用于管理應(yīng)用程序用戶界面的整體狀態(tài)
您的應(yīng)用的自定義視圖,可能有一些需要保留的自定義數(shù)據(jù)
UIKit允許您選擇要保留的用戶界面的哪些部分寡具。如果您已經(jīng)有處理狀態(tài)保存的自定義代碼秤茅,則可以繼續(xù)使用該代碼,并根據(jù)需要將部分遷移到UIKit狀態(tài)保存系統(tǒng)童叠。
在您的應(yīng)用程序中啟用狀態(tài)保存和恢復(fù)
狀態(tài)保存和恢復(fù)不是自動功能框喳,應(yīng)用程序必須選擇使用它。應(yīng)用程序通過在其應(yīng)用程序委托中實施以下方法來表明他們對該功能的支持:
應(yīng)用:shouldSaveApplicationState:
應(yīng)用:shouldRestoreApplicationState:
通常厦坛,這些方法的實現(xiàn)只是返回YES五垮,表示可以發(fā)生狀態(tài)保存和恢復(fù)。但是杜秸,要在不發(fā)生操作的情況下放仗,有條件地保留和恢復(fù)狀態(tài)的應(yīng)用程序可以返回NO。例如撬碟,在發(fā)布對您的應(yīng)用程序的更新后诞挨,您可能希望從應(yīng)用程序返回NO:shouldRestoreApplicationState:方法,如果您的應(yīng)用程序無法從先前版本有效地還原狀態(tài)呢蛤。
保存和恢復(fù)過程
狀態(tài)保存和恢復(fù)是一個選擇加入功能惶傻,并在您的應(yīng)用程序的幫助下工作。您的應(yīng)用程序標(biāo)識應(yīng)該保留的對象其障,UIKit會在適當(dāng)?shù)臅r候執(zhí)行保存和還原這些對象的工作银室。因為UIKit處理這么多的過程,所以它有助于了解它在幕后做的事情励翼,以便您了解自定義代碼如何適應(yīng)整體方案蜈敢。
在考慮狀態(tài)保護(hù)和恢復(fù)時,首先有助于分離兩個進(jìn)程汽抚。 UIKit會在適當(dāng)?shù)臅r間保留應(yīng)用的狀態(tài)抓狭,例如當(dāng)您的應(yīng)用程序從前臺移動到后臺時。當(dāng)UIKit確定需要新的狀態(tài)信息時殊橙,它會查看應(yīng)用程序的視圖和視圖控制器辐宾,以查看哪些應(yīng)該保留狱从。對于每個對象膨蛮,UIKit將保存相關(guān)數(shù)據(jù)寫入加密的磁盤文件。下一次您的應(yīng)用程序從頭開始季研,UIKit會查找該文件敞葛,如果存在,則使用它來嘗試恢復(fù)應(yīng)用程序的狀態(tài)与涡。因為文件是加密的惹谐,所以狀態(tài)保存和恢復(fù)只有在設(shè)備解鎖時才會發(fā)生持偏。
在恢復(fù)過程中,UIKit使用保留的數(shù)據(jù)重新構(gòu)建您的界面氨肌,但實際對象的創(chuàng)建將由您的代碼來處理鸿秆。因為您的應(yīng)用程序可能會自動從故事板文件加載對象,只有您的代碼知道需要創(chuàng)建哪些對象怎囚,哪些對象可能已經(jīng)存在卿叽,并且可以簡單地返回。在創(chuàng)建每個對象之后恳守,UIKit將使用保留的狀態(tài)信息來初始化它們考婴。
在保存和恢復(fù)過程中,您的應(yīng)用程序有很少的責(zé)任催烘。
在保存期間沥阱,您的應(yīng)用程序負(fù)責(zé):
告訴UIKit它支持狀態(tài)保存。
告訴UIKit應(yīng)該保留哪些視圖控制器和視圖伊群。
編碼任何保留對象的相關(guān)數(shù)據(jù)考杉。
在恢復(fù)期間,您的應(yīng)用程序負(fù)責(zé):
告訴UIKit它支持狀態(tài)恢復(fù)舰始。
提供(或創(chuàng)建)UIKit請求的對象奔则。
解碼保存對象的狀態(tài)并使用它將對象返回到之前的狀態(tài)。
在應(yīng)用程序的責(zé)任方面蔽午,最重要的是告訴UIKit在后續(xù)啟動期間保留哪些對象并提供這些對象易茬。 這兩個行為是設(shè)計應(yīng)用程序的保存和恢復(fù)代碼時應(yīng)該花費大部分時間的地方。他們也是您對實際過程最有控制力的地方及老。 為了理解為什么會這樣抽莱,它有助于看一個例子。
圖5-1顯示了用戶與幾個選項卡進(jìn)行交互之后骄恶,選項卡欄界面的視圖控制器層次結(jié)構(gòu)食铐。 您可以看到,一些視圖控制器將自動加載作為應(yīng)用程序的主要故事板文件的一部分僧鲁,但是某些視圖控制器已被呈現(xiàn)或被推送到不同選項卡中的視圖控制器上虐呻。在沒有狀態(tài)恢復(fù)的情況下,僅在主故事板文件中的視圖控制器將在后續(xù)啟動期間恢復(fù)寞秃。 通過添加對狀態(tài)恢復(fù)的支持斟叼,您可以保留所有的視圖控制器。
圖5-1示例視圖控制器層次結(jié)構(gòu)
UIKit僅保留那些具有分配的恢復(fù)標(biāo)識符的對象春寿。 恢復(fù)標(biāo)識符是一個字符串朗涩,用于標(biāo)識UIKit和您的應(yīng)用程序的視圖或視圖控制器。此字符串的值僅對您的代碼有意義绑改,但是此字符串的存在告訴UIKit它需要保留標(biāo)記的對象谢床。
在保存過程中兄一,UIKit會拖動應(yīng)用程序的視圖控制器層次結(jié)構(gòu),并保留具有恢復(fù)標(biāo)識符的所有對象识腿。如果視圖控制器沒有恢復(fù)標(biāo)識符出革,則該視圖控制器及其所有視圖和子視圖控制器都不會被保留。 圖5-2顯示了先前視圖層次結(jié)構(gòu)的更新版本渡讼,現(xiàn)在具有應(yīng)用于大多數(shù)(但不是全部)視圖控制器的恢復(fù)標(biāo)識蹋盆。
圖5-2添加恢復(fù)標(biāo)識查看控制器
根據(jù)您的應(yīng)用程序,保留每個視圖控制器可能或可能無意義硝全。如果視圖控制器顯示臨時信息栖雾,則可能不希望在恢復(fù)時返回到同一點,而是選擇將用戶返回到界面中更穩(wěn)定的位置伟众。
對于您選擇保留的每個視圖控制器析藕,您還需要確定以后如何還原它。 UIKit提供了兩種重建對象的方式。您可以讓您的應(yīng)用程序委托重新創(chuàng)建它,或者您可以將恢復(fù)類分配給視圖控制器欠拾,并讓該類重新創(chuàng)建它≈文啵恢復(fù)類實現(xiàn)UIViewControllerRestoration協(xié)議,并負(fù)責(zé)在還原時查找或創(chuàng)建指定的對象遮精。以下是有關(guān)何時使用每一個的提示:
如果視圖控制器在啟動時始終從應(yīng)用程序的主要故事板文件中加載居夹,請不要分配恢復(fù)類。相反本冲,讓您的應(yīng)用程序委托找到該對象准脂,或者利用UIKit的支持來隱式查找恢復(fù)的對象。
對于在啟動時未從主故事板文件加載的視圖控制器檬洞,請分配恢復(fù)類狸膏。最簡單的選擇是使每個視圖控制器都有自己的恢復(fù)類。
在保存過程中添怔,UIKit識別要保存并將每個受影響對象的狀態(tài)寫入磁盤的對象湾戳。每個視圖控制器對象都有機(jī)會寫出任何要保存的數(shù)據(jù)。例如广料,選項卡視圖控制器保存所選選項卡的標(biāo)識砾脑。UIKit還將視圖控制器的恢復(fù)類信息保存到磁盤。如果任何視圖控制器的視圖具有恢復(fù)標(biāo)識符性昭,UIKit也會要求它們保存狀態(tài)信息拦止。
下一次應(yīng)用程序啟動時县遣,UIKit照常加載應(yīng)用程序的主要故事板或nib文件糜颠,調(diào)用應(yīng)用程序委托的應(yīng)用程序:willFinishLaunchingWithOptions:方法汹族,然后嘗試恢復(fù)應(yīng)用程序的上一個狀態(tài)。它的第一件事是要求您的應(yīng)用程序提供與保留的控件對象匹配的一組視圖控制器對象其兴。如果給定的視圖控制器具有分配的恢復(fù)類顶瞒,則要求該類提供對象;否則,應(yīng)用程序代理被要求提供元旬。
保存過程的流程
圖5-3顯示了在狀態(tài)保存期間發(fā)生的高級事件榴徐,并顯示了應(yīng)用程序的對象如何受到影響。在保存甚至發(fā)生之前匀归,UIKit會通過調(diào)用應(yīng)用程序來發(fā)出應(yīng)用程序委托:shouldSaveApplicationState:method坑资。如果該方法返回YES,則UIKit將開始收集和編碼應(yīng)用程序的視圖和視圖控制器穆端。完成后袱贮,將編碼的數(shù)據(jù)寫入磁盤。
圖5-3高級流界面保存
下次應(yīng)用程序啟動時体啰,系統(tǒng)會自動查找保留的狀態(tài)文件攒巍,如果存在,則使用它來恢復(fù)您的界面荒勇。由于此狀態(tài)信息僅與應(yīng)用程序的上一個和當(dāng)前啟動周期相關(guān)柒莉,因此在應(yīng)用程序完成啟動后,該文件通常會被丟棄沽翔。只要恢復(fù)您的應(yīng)用程序出現(xiàn)錯誤兢孝,該文件也會被丟棄。例如仅偎,如果您的應(yīng)用程序在恢復(fù)過程中崩潰西潘,系統(tǒng)會在下一個啟動周期內(nèi)自動丟棄狀態(tài)信息,以避免再次崩潰哨颂。
恢復(fù)過程的流程
圖5-4顯示了狀態(tài)恢復(fù)期間發(fā)生的高級別事件喷市,并顯示了應(yīng)用程序的對象如何受到影響。標(biāo)準(zhǔn)初始化和UI加載完成后威恼,UIKit會通過調(diào)用應(yīng)用程序來調(diào)用應(yīng)用程序:shouldRestoreApplicationState:method來請求您的應(yīng)用程序委托狀態(tài)恢復(fù)品姓。這是您的應(yīng)用程序代理機(jī)會檢查保留的數(shù)據(jù),并確定是否可以恢復(fù)狀態(tài)箫措。如果是腹备,UIKit使用應(yīng)用程序委托和恢復(fù)類來獲取對應(yīng)用程序的視圖控制器的引用。然后向每個對象提供需要將其恢復(fù)到其先前狀態(tài)的數(shù)據(jù)斤蔓。
圖5-4恢復(fù)用戶界面的高級流程
雖然UIKit有助于還原各個視圖控制器植酥,但它不會自動恢復(fù)這些視圖控制器之間的關(guān)系。相反,每個視圖控制器負(fù)責(zé)編碼足夠的狀態(tài)信息以將其自身恢復(fù)到其先前的狀態(tài)友驮。例如漂羊,導(dǎo)航控制器對其導(dǎo)航堆棧上的視圖控制器的順序的信息進(jìn)行編碼。然后卸留,它稍后使用此信息將這些視圖控制器返回到堆棧上的先前位置走越。具有嵌入式子視圖控制器的其他視圖控制器同樣負(fù)責(zé)編碼他們以后要還原他們的孩子所需的任何信息。
注意:并非所有視圖控制器都需要對子視圖控制器進(jìn)行編碼耻瑟。例如旨指,標(biāo)簽欄控制器不編碼有關(guān)其子視圖控制器的信息。相反喳整,假設(shè)您的應(yīng)用程序遵循在創(chuàng)建標(biāo)簽欄控制器本身之前創(chuàng)建適當(dāng)?shù)淖右晥D控制器的常規(guī)模式谆构。
由于您負(fù)責(zé)重新創(chuàng)建應(yīng)用程序的視圖控制器,因此您可以在恢復(fù)過程中更改您的界面框都。例如低淡,您可以重新排序標(biāo)簽欄控制器中的選項卡,并仍然使用保留的數(shù)據(jù)將每個選項卡返回到之前的狀態(tài)
瞬项。當(dāng)然蔗蹋,如果您對視圖控制器層次結(jié)構(gòu)進(jìn)行了顯著的更改,例如在應(yīng)用程序更新期間囱淋,您可能無法使用保留的數(shù)據(jù)猪杭。
當(dāng)您排除視圖控制器組時會發(fā)生什么?
當(dāng)視圖控制器的恢復(fù)標(biāo)識符為零時妥衣,該視圖控制器及其管理的任何子視圖控制器不會自動保留皂吮。例如,在圖5-5中税手,由于導(dǎo)航控制器沒有恢復(fù)標(biāo)識符蜂筹,因此從保留的數(shù)據(jù)中省略它及其所有子視圖控制器和視圖。
圖5-5從自動保存過程中排除視圖控制器
即使您決定不保留視圖控制器芦倒,這并不意味著所有這些視圖控制器完全從視圖層次結(jié)構(gòu)中消失艺挪。 在啟動時,您的應(yīng)用程序仍然可以創(chuàng)建視圖控制器作為其默認(rèn)設(shè)置的一部分兵扬。例如麻裳,如果任何視圖控制器從應(yīng)用程序的故事板文件自動加載,它們?nèi)詫⒊霈F(xiàn)器钟,盡管是默認(rèn)配置津坑,如圖5-6所示。
圖5-6加載默認(rèn)視圖控制器
還有一點需要注意的是傲霸,即使視圖控制器沒有自動保留疆瑰,您仍然可以編碼對該視圖控制器的引用并手動保留眉反。在圖5-5中,第一導(dǎo)航控制器的三個子視圖控制器具有恢復(fù)標(biāo)識符穆役,即使父導(dǎo)航控制器沒有寸五。如果您的應(yīng)用程序委托(或任何保留的對象)編碼對這些視圖控制器的引用
,則會保留其狀態(tài)孵睬。即使導(dǎo)航控制器中的命令未被保存播歼,您仍然可以使用這些引用來重新創(chuàng)建視圖控制器伶跷,并在后續(xù)的啟動周期將它們安裝在導(dǎo)航控制器中掰读。
實施狀態(tài)保護(hù)和恢復(fù)清單
支持狀態(tài)保存和恢復(fù)需要修改您的應(yīng)用程序委托并查看控制器對象以對狀態(tài)信息進(jìn)行編碼和解碼。如果您的應(yīng)用程序有任何自定義視圖也具有可保留的狀態(tài)信息叭莫,那么您還需要修改這些對象蹈集。
在您的代碼中添加狀態(tài)保存和恢復(fù)時,請使用以下列表來提醒您需要編寫的代碼雇初。
(必需)實現(xiàn)應(yīng)用程序:shouldSaveApplicationState:和應(yīng)用程序:shouldRestoreApplicationState:應(yīng)用程序委托中的方法;請參閱在您的應(yīng)用程序中啟用狀態(tài)保存和恢復(fù)拢肆。
(必需)通過為其restoreIdentifier屬性分配一個非空字符串,將恢復(fù)標(biāo)識符分配給要保留的每個視圖控制器;請參閱標(biāo)記您的視圖控制器進(jìn)行保存靖诗。
如果要保存特定視圖的狀態(tài)郭怪,請將非空字符串分配給它們的restoreIdentifier屬性;看保持你的意見狀態(tài)。
(必需)從應(yīng)用程序顯示應(yīng)用程序的窗口:willFinishLaunchingWithOptions:應(yīng)用程序委托的方法刊橘。狀態(tài)恢復(fù)機(jī)構(gòu)需要窗口鄙才,以便可以恢復(fù)應(yīng)用程序界面的滾動位置和其他相關(guān)位。
將修復(fù)類分配給相應(yīng)的視圖控制器促绵。 (如果不這樣做攒庵,您的應(yīng)用程序委托被要求在還原時提供相應(yīng)的視圖控制器。)請參閱在啟動時恢復(fù)視圖控制器败晴。
(推薦)使用encodeRestorableStateWithCoder:和decodeRestorableStateWithCoder編碼和解碼視圖的狀態(tài)并查看控制器:這些對象的方法;請參閱編碼和解碼視圖控制器的狀態(tài)浓冒。
使用應(yīng)用程序?qū)?yīng)用程序的任何版本信息或其他狀態(tài)信息進(jìn)行編碼和解碼:willEncodeRestorableStateWithCoder:和應(yīng)用程序:didDecodeRestorableStateWithCoder:應(yīng)用程序委托的方法;請參閱保存應(yīng)用程序的高級狀態(tài)。
作為表視圖和集合視圖的數(shù)據(jù)源的對象應(yīng)實現(xiàn)UIDataSourceModelAssociation協(xié)議尖坤。雖然不是必需的稳懒,但是該協(xié)議有助于在這些類型的視圖中保留所選和可見的項目。請參閱實施易于維護(hù)的數(shù)據(jù)源慢味。