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