不同的應(yīng)用有不同的需求,但是有些行為是大多數(shù)類型的應(yīng)用都需要的。以下部分提供了有關(guān)如何在應(yīng)用中實(shí)現(xiàn)幾個(gè)特定功能類型的指導(dǎo)。
隱私策略
保護(hù)用戶的隱私是應(yīng)用設(shè)計(jì)階段需要重點(diǎn)考慮的問(wèn)題。隱私保護(hù)包括保護(hù)用戶的數(shù)據(jù)、用戶的身份識(shí)別信息、以及個(gè)人信息。系統(tǒng)框架已經(jīng)為管理數(shù)據(jù)(例如通訊錄)提供了隱私控制,但是應(yīng)用應(yīng)該采取措施來(lái)保護(hù)自身的數(shù)據(jù)。
使用磁盤(pán)加密來(lái)保護(hù)數(shù)據(jù)
使用內(nèi)置硬件來(lái)存儲(chǔ)經(jīng)過(guò)磁盤(pán)格式加密的文件,并根據(jù)需要進(jìn)行解密。當(dāng)用戶設(shè)備被鎖定時(shí),保護(hù)文件無(wú)法訪問(wèn),即使是創(chuàng)建它們的應(yīng)用。用戶必須解鎖設(shè)備(通過(guò)輸入相應(yīng)的密碼)應(yīng)用才能夠訪問(wèn)被保護(hù)的文件。
絕大多數(shù)iOS設(shè)備都提供數(shù)據(jù)保護(hù)。數(shù)據(jù)保護(hù)也取決于如下必要條件
- 用戶設(shè)備上的文件系統(tǒng)必須支持?jǐn)?shù)據(jù)保護(hù),大多數(shù)設(shè)備都支持此項(xiàng)行為。
- 用戶必須為設(shè)備設(shè)置密碼鎖。
為了保護(hù)文件,你要為文件添加一個(gè)屬性,用來(lái)指明想要的保護(hù)級(jí)別??梢允褂肗SData類或者NSFileManager類來(lái)添加這個(gè)屬性。當(dāng)寫(xiě)入新文件時(shí),你可以使用 NSData類的writeToFile:options:error:方法(帶有合適的寫(xiě)入選項(xiàng)參數(shù)值)。對(duì)于已存在的文件,你可以使用NSFileManager類的setAttributes:ofItemAtPath:error:方法來(lái)設(shè)置或改變NSFileProtectionKey的值。當(dāng)使用這些方法時(shí),為文件指定一個(gè)保護(hù)級(jí)別。保護(hù)級(jí)別如下所示:
- 沒(méi)有保護(hù)——文件已加密,但不受密碼保護(hù),并在設(shè)備鎖定時(shí)可用。指定NSDataWritingFileProtectionNone 選項(xiàng) (NSData) 或NSFileProtectionNone 屬性 (NSFileManager).。
- 完全保護(hù)——文件已加密,并且在設(shè)備鎖定時(shí)無(wú)法訪問(wèn)。指定 NSDataWritingFileProtectionComplete 選項(xiàng) (NSData)或NSFileProtectionComplete 屬性 (NSFileManager).
- 完全保護(hù),除非已經(jīng)打開(kāi)——文件已加密。當(dāng)設(shè)備鎖定時(shí),關(guān)閉的文件不可訪問(wèn)。但是如果鎖定前文件是打開(kāi)的,那么鎖定后文件依然可被訪問(wèn)。指定NSDataWritingFileProtectionCompleteUnlessOpen 選項(xiàng) (NSData) 或 NSFileProtectionCompleteUnlessOpen 屬性 (NSFileManager).
- 完全保護(hù),直到首次登錄——文件已加密且無(wú)法訪問(wèn),直到設(shè)備已啟動(dòng)且用戶解鎖過(guò)一次之后。指定NSDataWritingFileProtectionCompleteUntilFirstUserAuthentication 選項(xiàng) (NSData) 或者NSFileProtectionCompleteUntilFirstUserAuthentication 屬性 (NSFileManager).
如果你要保護(hù)文件,你的應(yīng)用必須準(zhǔn)備好失去這個(gè)文件的訪問(wèn)權(quán)。當(dāng)完全文件保護(hù)被啟用時(shí),應(yīng)用在用戶鎖定設(shè)備的時(shí)候失去對(duì)文件讀寫(xiě)的能力。你可以跟蹤狀態(tài)的改變以便使用下面的技術(shù)來(lái)保護(hù)文件:
- 應(yīng)用委托實(shí)現(xiàn)applicationProtectedDataWillBecomeUnavailable: 和 applicationProtectedDataDidBecomeAvailable: 方法.
- 任何對(duì)象都可以注冊(cè)UIApplicationProtectedDataWillBecomeUnavailable 和 UIApplicationProtectedDataDidBecomeAvailable 通知.
- 任何對(duì)象都可以檢查UIApplication對(duì)象的protectedDataAvailable屬性,來(lái)確定文件當(dāng)前是否可以訪問(wèn)。
對(duì)于新文件,推薦你在寫(xiě)入文件前啟用數(shù)據(jù)保護(hù)。如果你正在使用writeToFile:options:error:方法寫(xiě)入一個(gè)NSData對(duì)象到磁盤(pán),那么它自動(dòng)就實(shí)現(xiàn)了數(shù)據(jù)保護(hù)。對(duì)于已存在的文件,使用新的受保護(hù)的版本替換舊的不受保護(hù)的版本來(lái)實(shí)現(xiàn)數(shù)據(jù)保護(hù)。
識(shí)別應(yīng)用的唯一用戶
識(shí)別應(yīng)用的用戶可以帶來(lái)明確的好處。如果你只需要區(qū)別應(yīng)用不同的用戶,iOS提供了標(biāo)識(shí)符來(lái)幫助完成此功能。但是,如果你需要高級(jí)別的安全性,你可能需要做更多工作。例如,一個(gè)提供金融服務(wù)的應(yīng)用會(huì)希望提示用戶提供登錄憑證,以確保用戶被批準(zhǔn)訪問(wèn)特定賬戶。
重要:當(dāng)識(shí)別用戶時(shí),始終要明確表達(dá)你打算使用獲取的信息做什么。識(shí)別用戶以便跟蹤他們的行為是不可接受的。
以下是一些可能需要你識(shí)別用戶的常見(jiàn)情況,以及如何實(shí)現(xiàn)它們的解決方案:
- 你想連接用戶到服務(wù)器上的特定賬戶。包活一個(gè)要求用戶安全地輸入他們賬戶信息的登錄界面??偸峭ㄟ^(guò)以加密格式保存從用戶處搜集的賬戶信息以保證安全。
- 你需要區(qū)分在不同設(shè)備上運(yùn)行的實(shí)例。使用UIDevice類的identifierForVendor屬性來(lái)獲取一個(gè)ID。一個(gè)用戶可以有多個(gè)設(shè)備,該ID值在每個(gè)設(shè)備上都不同。
- 你想因廣告的目的來(lái)識(shí)別用戶。使用ASIdentifierManager類的advertisingIdentifier屬性來(lái)獲取用戶的ID。
因?yàn)橛脩舯辉试S在所有他們的設(shè)備上運(yùn)行應(yīng)用,蘋(píng)果公司不提供識(shí)別同一個(gè)用戶在不同設(shè)備上的方式。如果你需要識(shí)別特定的用戶,你必須使用UUIDs、登錄賬號(hào)、或者其他類型的身份識(shí)別系統(tǒng)來(lái)提供你自己的解決方案。
遵守限制
用戶可以設(shè)置限制,這種限制指明要在應(yīng)用中使用的媒體的評(píng)級(jí)。如果你的應(yīng)用基于限制播放媒體或修改媒體的行為,你需要確定當(dāng)前的設(shè)置以及在設(shè)置改變時(shí)進(jìn)行響應(yīng)。
想要得到當(dāng)前的設(shè)置,獲取standardUserDefaults對(duì)象并使用objectForKey:方法來(lái)查看下面這些鍵的值:
| 媒體評(píng)級(jí)鍵 | 值 |
|---|---|
| com.apple.content-rating.ExplicitBooksAllowed | Boolean。如果值為NO,則露骨的書(shū)本不被允許。 |
| com.apple.content-rating.ExplicitMusicPodcastsAllowed | Boolean。如果值為NO,則露骨的音樂(lè)、電影、以及播客節(jié)目都不被允許。 |
| com.apple.content-rating.AppRating | NSNumber。該鍵的值在0-1000的范圍內(nèi)。應(yīng)用的評(píng)級(jí)不允許超過(guò)當(dāng)前值。 |
| com.apple.content-rating.MovieRating | NSNumber。該鍵的值在0-1000的范圍內(nèi)。電影的評(píng)級(jí)不允許超過(guò)當(dāng)前值。 |
| com.apple.content-rating.TVShowRating | NSNumber。該鍵的值在0-1000的范圍內(nèi)。TV內(nèi)容的評(píng)級(jí)不允許超過(guò)當(dāng)前值。 |
注意:如果objectForKey: 對(duì)于特定鍵返回nil,這意味著關(guān)于此特定限制的信息不可用。應(yīng)用可以使用它自己的政策來(lái)決定合適的評(píng)級(jí)。
要查明何時(shí)用戶更改了限制,請(qǐng)注冊(cè)NSUserDefaultsDidChangeNotification通知。standardUserDefaults對(duì)象在應(yīng)用檢測(cè)到一個(gè)持久域(persistent domains)中的首選項(xiàng)發(fā)生更改的時(shí)候,發(fā)送這個(gè)通知給應(yīng)用。
應(yīng)用評(píng)級(jí)是針對(duì)國(guó)家代碼定義的,并得到廣泛應(yīng)用的。表5-1展示了美國(guó)應(yīng)用評(píng)級(jí)相關(guān)聯(lián)的值。
Table 5-1 應(yīng)用評(píng)級(jí)
| 評(píng)級(jí)名稱 | 數(shù)值 |
|---|---|
| 4+ | 100 |
| 9+ | 200 |
| 12+ | 300 |
| 17+ | 600 |
電影和電視的評(píng)級(jí)因國(guó)家不同而異。如果國(guó)家或地區(qū)沒(méi)有為電影或電視節(jié)目指定評(píng)級(jí)系統(tǒng),應(yīng)用應(yīng)該使用它自己的合適地評(píng)級(jí)策略。雖然大多數(shù)地區(qū)定義了電影評(píng)級(jí),但只有少數(shù)地區(qū)定義了電視節(jié)目的評(píng)級(jí)。
一個(gè)地區(qū)可以定義幾個(gè)評(píng)級(jí)級(jí)別,每個(gè)級(jí)別與一個(gè)描述評(píng)級(jí)的名字和一個(gè)評(píng)級(jí)0-1000的范圍。例如,美國(guó)使用字符串“G”和數(shù)字100來(lái)指定最低一級(jí)的電影評(píng)級(jí)級(jí)別。
即使應(yīng)用不播放媒體,你也可能想把你自己的評(píng)級(jí)系統(tǒng)映射到電視節(jié)目評(píng)級(jí)系統(tǒng)上。例如,游戲可以只有當(dāng)美國(guó)電影評(píng)級(jí)為“R”被允許的時(shí)候才可以啟用某些功能。想要查看當(dāng)前的評(píng)級(jí)列表,請(qǐng)下載本文檔的附件(鏈接位于文檔底部)。
支持多個(gè)iOS版本
支持最新以及較早iOS版本的應(yīng)用,必須使用運(yùn)行時(shí)來(lái)檢測(cè)來(lái)阻止在老版本上運(yùn)行新API。當(dāng)應(yīng)用嘗試使用當(dāng)前操作系統(tǒng)不允許的功能時(shí),運(yùn)行時(shí)檢查可以防止此種情況下崩潰的發(fā)生。
以下是你可以使用的幾個(gè)檢查類型。
- 要確定一個(gè)類是否存在,就看它的Class對(duì)象是否為nil。使用下面類似的方法進(jìn)行判斷。
if ([UIPrintInteractionController class]) {
// Create an instance of the class and use it.
}
else {
// The print interaction controller is not available so use an alternative technique.
}
- 想要確定現(xiàn)有類中是否有一個(gè)方法可用,使用instancesRespondToSelector:類方法,或者respondsToSelector:對(duì)象方法。
- 想要判斷基于C的函數(shù)是否可用,執(zhí)行函數(shù)名與NULL的比較。如果符號(hào)不是NULL,就可以調(diào)用函數(shù)。例如:
if (UIGraphicsBeginPDFPage != NULL) {
UIGraphicsBeginPDFPage();
}
更多關(guān)于如何編寫(xiě)代碼以支持多開(kāi)發(fā)目標(biāo)的信息和例子,參見(jiàn)SDK Compatibility Guide。
啟動(dòng)的時(shí)候保留應(yīng)用的視覺(jué)外觀
即使你的應(yīng)用支持后臺(tái)運(yùn)行,它也不是永遠(yuǎn)運(yùn)行。在有些時(shí)候,系統(tǒng)可能會(huì)需要終止應(yīng)用來(lái)為當(dāng)前的前臺(tái)應(yīng)用釋放空間。但是,用戶應(yīng)該永遠(yuǎn)不需要關(guān)心應(yīng)用是否在運(yùn)行。從用戶的角度看,退出應(yīng)用看上去和臨時(shí)中斷是一樣的。當(dāng)用戶回到應(yīng)用時(shí),應(yīng)用應(yīng)該總是回到之前退出時(shí)的位置,這樣用戶就能繼續(xù)之前的任務(wù)了。該行為提供了一個(gè)很好的用戶體驗(yàn),而且UIKit內(nèi)置這些轉(zhuǎn)換狀態(tài),所以相對(duì)容易實(shí)現(xiàn)。
UIKit內(nèi)建的狀態(tài)保存系統(tǒng)提供了簡(jiǎn)單但靈活的基礎(chǔ)功能。這些基本功能的工作是在合適的時(shí)候驅(qū)動(dòng)保存和恢復(fù)的進(jìn)程。要想做到這點(diǎn),UIKit需要來(lái)自應(yīng)用的幫助。因?yàn)橹挥心憷斫饽銘?yīng)用的內(nèi)容,所以只有你才能寫(xiě)保存和恢復(fù)內(nèi)容的代碼。當(dāng)你更新應(yīng)用的UI的時(shí)候,也只有你知道如何把舊的儲(chǔ)存的內(nèi)容映射到界面中新的對(duì)象中。
有三個(gè)你必須考慮狀態(tài)保存的地方:
- 應(yīng)用的委托對(duì)象,它管理應(yīng)用的頂層狀態(tài)
- 應(yīng)用的視圖控制器對(duì)象,它管理應(yīng)用用戶界面的整體狀態(tài)
- 應(yīng)用自定義視圖,可能有一些需要保存的自定義數(shù)據(jù)
UIKit允許你選擇用戶界面的局部進(jìn)行保存。如果你已經(jīng)有自定義的代碼來(lái)處理狀態(tài)保存,你可以繼續(xù)使用這些代碼,并根據(jù)需要把部分移動(dòng)到UIKit的狀態(tài)保存系統(tǒng)。
在應(yīng)用中啟用狀態(tài)保存和恢復(fù)
狀態(tài)保存和恢復(fù)不是自動(dòng)功能,應(yīng)用必須選擇使用它。應(yīng)用通過(guò)實(shí)現(xiàn)它的委托中的如下方法來(lái)表明它對(duì)該功能的支持:
application:shouldSaveApplicationState:
application:shouldRestoreApplicationState:
通常,你的這些方法的實(shí)現(xiàn)要返回YES,以便表明這個(gè)狀態(tài)存儲(chǔ)和恢復(fù)能夠發(fā)生。但是,如果不想讓此功能發(fā)生,可以讓方法返回NO。例如,在釋放和更新應(yīng)用之后,如果應(yīng)用不能有效的從之前的版本回復(fù)狀態(tài),你可以讓application:shouldRestoreApplicationState:方法返回NO。
(未完待續(xù)......)