官方地址:iOS App Programming Guide -> iCloud Storage
iCloud支持兩種應用存儲:
- document storage:存儲用戶文檔和應用數據到用戶的iCloud賬戶
- key-value data storage:分享小量的非關鍵配置數據到應用的多個實例
iCloud App的設計考慮
首 先需要確認的是采用document storage還是key-value data storage。document storage用於存儲應用數據,要么是應用創建並私有管理的數據,要么是用戶創建的數據。所有用戶面對的數據都應該是document storage,例如用戶創建的文檔。key-value data storage主要用於非關鍵的配置數據,你希望在多個app實例中共享,例如應用使用的參數和配置信息(典型的例子如Newsstand應用中用戶上一次閱讀的刊物和閱讀位置)。
document storage 和 key-value data storage的區別:
屬性 | Document Storage | Key-Value storage |
管理的數據類型? | 文件和目錄 | 只能是Property-list數據 |
什么時候應該使用? | 使用Document Storage來管理應用的關鍵數據。與應用main data model直接相關的文件和數據,總是應該使用Document Storage。如用戶文檔、私有的app數據文件、以及應用或用戶生成的數據文件 | 參數或其它配置數據,如果需要在多個app實例之間共享,並且不是關鍵數據,就可以使用key-vlaue storage。只能存儲property list數據,並且容量有限。 |
是否需要file presenter和file coordinator | 是 | 否 |
怎樣定位數據? | 使用 NSMetadataQuery 對象來查找文件 | 使用默認的 NSUbiquitousKeyValueStore 對象來獲取已知key對應的值 |
如何管理數據? | 使用NSFileManager類來管理文件和目錄。使用標准文件系統函數來打開、關閉、讀取和寫入文件 | 使用默認的NSUbiquitousKeyValueStore 對象來獲取和設置key和value |
能存儲多少數據? | 只受用戶iCloud賬戶的空間限制 | 限制為64KB(單個key也限制為64KB) |
怎樣處理沖突? | 應用的 file presenters 必須手工解決沖突 | 最后設置的值總是當前值。設備提供的時間戳用於確定最新的值 |
要求設置哪個entitlement? | com.apple.developer.ubiquity-container-identifiers | com.apple.developer.ubiquity-kvstore-identifier |
數據什么時候同步? | 設備端發生變化時,iCloud總是會拉取文件元數據和數據;設備總是會拉取文件元數據,但是直到應用試圖使用文件時才會拉取文件數據 | 定期在設備和iCloud之間傳輸key-value數據 |
怎樣在運行時檢查iCloud可用? | 對某個你已經注冊的容器目錄調用 URLForUbiquityContainerIdentifier: 方法,如果方法返回nil,表示document storage不可用 | 調用 NSUbiquitousKeyValueStore 的 synchronize 方法,如果返回YES,iCloud可用,並且有修改同步到本地用戶默認數據庫;如果返回NO,iCloud要么不可用,要么沒有變化需要同步。無論如何,都可以直接使用本地的用戶默認數據庫。 |
系統提供了什么用戶界面支持? | 沒有,應用負責提供支持iCloud的信息和界面。 | 沒有,多數情況下,你不應該讓用戶知道key-value數據存儲在本地還是iCloud中。 |
另一個設計考慮是應用的用戶界面如何整合iCloud支持。特別是文檔,有時候你需要提醒用戶文檔的狀態,比如是否已經下載、版本沖突需要解決等。一般都需要在界面上增加一些不引人注目的元素,以在適當的時候提示用戶。
配置應用的iCloud Entitlements
使用iCloud的應用必須以iCloud特定的Entitlements簽名。這些entitlements為應用提供一層安全性,確保只有你的應用才能訪問自己創建的文檔。系統也依賴於你提供的Entitlement值來區分用戶iCloud賬戶中你的應用與其它應用的文檔。
Xcode中啟用iCloud Entitlements:
- 選擇應用的target
- 選擇Summary
- 在Entitlements中,勾選"Enable Entitlements"
當 你啟用App target的Entitlements時,Xcode自動為你的應用配置了document storage和key-value data storage。每個Entitlement包含一個key,是一個或多個容器標識字符串。容器標識字符串標識了iCloud中的一個容器目錄,你用來存儲應用的文件。
Xcode按以下方式來配置Entitlements:
- iCloud容器域標識了應用在用戶iCloud存 儲中能夠訪問的容器目錄(這個域對應於com.apple.developer.ubiquity-container-identifiers)。你添 加到這個列表的字符串必須匹配你的團隊創建的應用bundle ID。Xcode使用當前app的bundle ID來指定第一個字符串,如果你希望多個app共享一個main容器目錄,你可以修改為不同的bundle ID。你還可以為團隊的其它應用添加額外的bundle ID(第一個字符串必須不包含任何通配符,隨后的字符串則可以包含通配符)
- iCloud的key-value存儲域包含應用存儲到iCloud的key-value data storage的單個容器標識字符串(對應於 com.apple.developer.ubiquity-kvstore-identifier)
你 在Xcode中設置的bundle ID並不是完整限定的容器標識字符串。完整限定的容器標識的格式 是: <TEAM_ID>.<BUNDLE_IDENTIFIER>,其中<TEAM_ID>是10個字符的團隊標 識;<BUNDLE_IDENTIFIER> 則是iCloud容器域中的某個bundle ID。當在代碼中獲取某個容器目錄的URL時,你需要傳遞完整限定的字符串給 URLForUbiquityContainerIdentifier: 方法。不過你也可以傳遞nil,來獲取列表中的第一個容器目錄的URL
通過在Entitlements中指定多個容器標識,使用iCloud document storage的應用可以讀取和寫入內容到多個容器目錄。iCloud容器域允許你指定多個字符串。第一個字符串是應用的main容器標識,任何額外的字符串則代表你其它應用的容器標識。查找時會返回所有可用容器目錄中的所有文件。
使用iCloud Document Storage
iCloud Document Storage讓你將文件和目錄移動到用戶的iCloud賬戶,並在那里管理這些文件。在某個設備上修改文件或目錄,會先存儲在本地,然后再通過本地daemon進程push到iCloud。文件傳輸對應用是透明的,因此應用只需直接操作文件。
設計應用使用iCloud Document Storage,需要一些重大的應用修改,主要包括:
- 應用執行的早期,調用 URLForUbiquityContainerIdentifier: 方法檢查iCloud是否啟用。擴展應用Sandbox來包含應用請求的每個容器目錄,也需要調用這個方法。
- 顯式地整合 file presenters(如UIDocument類)到應用的數據層
- 顯式地移動文件到iCloud
- 准備好處理版本沖突
- 使用查找來定位iCloud中的文件
- 處理文件在iCloud中,但是沒有完全下載到本地設備的情況;可能需要向用戶提供及時的反饋
- 如果要在iCloud中存儲live database,使用Core Data,不要使用SQLite
- 如果應用還有Mac OS X版本,為所有應用使用通用文檔格式
App支持iCloud的大部分工作都在數據層。與iCloud的交互也主要是應用要存儲使用的文件和目錄。不過底層數據變化時,用戶界面也需要一定的修改,以通知用戶相關的狀態。當然,應用應該盡可能地讓用戶無需關心本地還是iCloud存儲。
檢查iCloud Document Storage是否可用
每個Apple ID用戶都有一個免費的iCloud賬戶,但是用戶可能禁用某個設備的iCloud。因此使用iCloud接口之前,必須先調用 URLForUbiquityContainerIdentifier: 方法檢確定iCloud是否可用。返回nil表示不可用,返回URL表示可用
第一次對指定的容器目錄調用 URLForUbiquityContainerIdentifier: 方法,iOS會擴展應用Sandbox來包含該容器目錄。因此需要至少成功調用一次該方法,以確保iCloud可用,main容器目錄也可以訪問。
整合 File Presenters 到應用
iCloud中存儲的所有文件和目錄都由file presenter對象管理;你對這些文件和目錄的修改都必須通過一個file coordinator對象。
file presenter實現了 NSFilePresenter 協議,主要的職責是作為特定文件或目錄的響應代理。在外部源能夠修改一個文件之前,注冊的file presenter會得到通知,並有機會執行任何必要的簿記(bookkeeping)工作。
當應用想要修改一個文件時,它必須通過一個 NSFileCoordinator 對象來執行修改,本質上會鎖住文件。file coordinator 阻止外部源修改文件,並且遞送相關的通知給其它 file presenters。
整 合 file presenter 到應用最簡單的方法是使用 UIDocument 類。這個類實現了 NSFilePresenter 協議,並為你處理了所有文件相關的管理。應用唯一需要做的事情,就是在得到通知時,讀取和寫入文檔數據。不管是用戶生成內容的文件(因此直接顯示給用戶),還是應用替用戶創建的文件(無需用戶交互),都可以使用UIDocument。
操作iCloud中的文件和目錄
iCloud文件和目錄和本地文件目錄一樣,應用使用相同的技術來管理文件和目錄。你可以打開、創建、移動、復制、讀取、寫入、刪除、以及其它操作。本地文件目錄和iCloud文件目錄的唯一區別是訪問的URL不同。本地文件目錄的URL相對於應用Sandbox,而iCloud文件目錄的URL則相對於相應的iCloud容器目錄。
要移動一個文件或目錄到iCloud:
- 在應用Sandbox中創建本地文件或目錄。使用的時候,必須由file presenter來管理文件或目錄。如UIDocument
- 使用 URLForUbiquityContainerIdentifier: 方法獲取iCloud容器目錄的URL
- 使用容器目錄URL來構建一個新的URL,指定文件或目錄在iCloud中的存儲位置
- 調用 NSFileManager 的 setUbiquitous:itemAtURL:destinationURL:error: 方法移動文件或目錄到iCloud。絕對不要在應用的主線程中調用這個方法,否則可能會長時間阻塞主線程,或者與應用所擁有的file presenter產生死鎖。
移動一個文件或目錄到iCloud時,系統從應用Sandbox中復制該item到private本地存儲,這樣才能被iCloud daemon監測到。盡管文件此時已經不在應用Sandbox中,應用仍然對其擁有完全訪問。雖然文件仍然有一份拷貝保留在當前設備的本地,文件同時還發送到了iCloud,這樣就能分布到其它設備去。iCloud daemon處理了所有工作,確保本地拷貝與iCloud是相同的。因此從應用的角度來說,文件就是在iCloud中。
你對iCloud中的文件和目錄的所有修改都需要使用一個 file coordinator 對象。包括移動、刪除、復制、重命名等操作。file coordinator確保iCloud daemon不會同時修改文件或目錄,並確保你修改時能夠及時地通知其它人。
命名文件和目錄時,盡量使用字母數字,避免使用特殊標點和其它特殊字符。同時你還應該假設文件名是大小寫不敏感的(因為iCloud支持Windows)。最后盡量保持文件名簡單,以確保這些文件能夠在不同文件系統中正確地處理。
選擇一種響應版本沖突的策略
iCloud文件的版本沖突不可避免,因此應用必須對沖突采取一種解決策略。當應用的兩個實例同時修改一個文件並傳輸給iCloud時就會發生沖突。iCloud會保存所有沖突的版本,並通知應用的file presenter發生了沖突需要解決。
App應該盡快地嘗試解決版本沖突,當沖突發生時,其中一個文件被指定為current file,其它所有版本都是沖突版本。當前文件和沖突版本文件都由 NSFileVersion 對象來管理,可以通過類方法來獲取。
解決沖突:
- 使用類方法 currentVersionOfItemAtURL: 獲取當前文件版本
- 使用類方法 unresolvedConflictVersionsOfItemAtURL: 獲取所有沖突版本的數組
- 對每個file version對象,執行以下任何動作來解決沖突:[list=1]
- 如果實際可行的話,合並沖突文件修改的數據
- 如果能夠安全地執行而不丟失數據的話,忽略某個沖突版本
- 提示用戶選擇保留哪個版本的文件(當前文件或沖突文件),這是最后的選擇。
更新當前文件:
- 如果當前文件勝利(winner),不需要更新當前文件
- 如果某個沖突版本勝利(winner),使用 coordinated write 操作,以沖突版本的文件內容覆蓋當前文件
- 如果用戶選擇保存沖突版本為另一個名字,以該沖突版本的內容創建一個新文件
設置所有沖突版本對象的 resolved 屬性為YES。設置這個屬性會導致沖突版本對象(及相應的文件)從用戶的iCloud storage中刪除。如果使用UIDocument類,你通過 observing 文檔狀態變化通知,並檢查 documentState 屬性來判斷是否發生沖突
如果使用自定義 file presenter,每當報告有一個新版本時,你都應該檢查它是否沖突版本。
整合查找(Search)到應用基礎架構
和應用Sandbox不同,iCloud中的文件添加和刪除,你的應用可能都不會直接知道。在這台設備上創建的文件,最終會出現在另一台設備中。如果應用不主動查找文件,那就不能及時地出現在用戶界面中。因此應用需要使用 NSMetadataQuery 對象來查找iCloud容器目錄中的文件或目錄。
當應用在前台時,你可以保留一個 metadata query 一直運行,來接收文件添加或刪除的通知;應用進入后台時,就停止這個 metadata query 查詢。
只有 iCloud 啟用,並且相應的容器目錄已經創建時,metadata查詢才會有返回結果。在運行時,確保使用 URLForUbiquityContainerIdentifier: 方法來檢測iCloud已經啟用,而且應用支持的容器目錄也可用。這個方法在容器目錄不存在時,會自動創建出來。
Metadata 查找應用entitlement中設置的所有容器目錄,並返回合並后的所有結果。如果你希望只查找一個容器目錄,可以使 用 URLForUbiquityContainerIdentifier: 方法來獲得該容器目錄的URL,然后使用 NSFileManager 類來獲取目錄內容的靜態列表。
確定文件或目錄的傳輸狀態
你寫到iCloud容器目錄的item會盡可能快地自動傳輸到iCloud服務器。但是由於網絡和設備類型的原因,文件或目錄可能不會立即下載到設備或上傳到服務器。如果你需要確定文件的狀態,可以使用 NSURL 的 getResourceValue:forKey:error: 方法,來獲取以下屬性的值:
- NSURLIsUbiquitousItemKey:表示item是否存儲在iCloud
- NSURLUbiquitousItemIsDownloadedKey:表示當前版本是否已經下載並且可訪問
- NSURLUbiquitousItemIsDownloadingKey:表示當前版本是否正在下載並且暫時不可用
- NSURLUbiquitousItemPercentDownloadedKey:對於正在下載的item,表示已經下載的修改的百分比。可以使用這個值來更新進度條。
- NSURLUbiquitousItemIsUploadedKey:表示本地的修改是否成功上傳到iCloud服務器
- NSURLUbiquitousItemIsUploadingKey:表示本地的修改是否正在上傳到服務器
- NSURLUbiquitousItemPercentUploadedKey:對於正在上傳的item,表示當前已經上傳的修改的百分比
雖然iCloud服 務器會非常努力地拉取應用在本地做的修改,但是iOS設備通常卻不會主動從服務器拉取修改,除非你試圖訪問該文件。如果你試圖打開一個正在下載的文 件,iOS會阻塞發起打開請求的線程,直到文件被完全下載並且可用。因此如果你擔心潛在的延遲,就根據需要檢查文件的當前狀態,同時更新用戶界面,提示用 戶當前文件正在下載,暫時不可用。
使用尚未下載完成的文件
iCloud中的文件發生改變時,iOS設備不會自動下載這些修改數據。相反iOS設備會下載文件的元數據,因此知道此時文件已經有修改。實際修改的數據只有以下情況發生時,才會被下載:
- 應用試圖打開或訪問文件
- 應用調用 startDownloadingUbiquitousItemAtURL:error: 方法,顯式地下載文件修改
如果應用打開尚未下載完成的文件,用於打開文件的 file coordinator 會阻塞你的應用,直到文件或修改被完全下載。如果文件或修改比較大,可能會導致很差的用戶體驗,因此試圖打開一個文件之前,應該首先檢查文件的下載狀態。NSURL 類定義了iCloud item相關的屬性,可以檢查iCloud文件的狀態
檢查文件是否已經下載完成:
- (BOOL)downloadFileIfNotAvailable:(NSURL*)file {
NSNumber* isIniCloud = nil;
if ([file getResourceValue:&isIniCloud forKey:NSURLIsUbiquitousItemKey error:nil]) {
// If the item is in iCloud, see if it is downloaded.
if ([isIniCloud boolValue]) {
NSNumber* isDownloaded = nil;
if ([file getResourceValue:&isDownloaded forKey:NSURLUbiquitousItemIsDownloadedKey error:nil]) {
if ([isDownloaded boolValue])
return YES;
// Download the file.
NSFileManager* fm = [NSFileManager defaultManager];
[fm startDownloadingUbiquitousItemAtURL:file error:nil];
return NO;
}
}
}
// Return YES as long as an explicit download was not started.
return YES;
}
為iCloud調整用戶界面
所有為了iCloud所做的用戶界面調整,都應該盡量不引人注意。當iCloud不可用時,你存儲在iCloud中的文檔和你存儲在本地是完全一樣的。唯一的區別是文件系統中的位置。因此大部分用戶界面都應該保持一致。
以下情況可能需要針對iCloud修改用戶界面:
- 當用戶生成的文檔在使用之前必須被下載。只有你提供了文檔瀏覽器,才需要讓用戶來控制是否下載文檔。應用使用的私有文件,應該在不可用時自動去服務器下載。你用來提示用戶的信息應該盡量友好,並提供用戶“開始文檔下載”的選項。如果下載時間可能超過幾秒鍾,你需要顯示一個當前下載進度。
- 當出現必須由用戶解決的版本沖突。如果應用需要用戶協助,才能解決沖突,就應該友好地提示沖突信息,但千萬不要顯示警告,或其它任何破壞性的界面。
- 當你希望提供用戶選項,為應用啟用或禁用iCloud時。如果應用包含一個Settings Bundle或者內部的參數設置,你可以提供一個參數,讓用戶選擇是否使用iCloud。
iCloud結合Database使用
只有應用使用Core Data來管理數據庫時,才能將SQLite數據庫整合到iCloud。不支持使用SQLite接口訪問iCloud中的live數據庫,這樣做很可能會毀壞你的數據庫。
但是只要你遵守一些額外的步驟,來設置Core Data結構,你就可以創建基於SQLite的Core Data,從而啟用iCloud支持。當然,其它類型的Core Data Store(不基於SQLite),則無需修改可以直接支持iCloud。
使用Core Data和SQLite store時,實際的數據庫文件不會傳輸到iCloud服務器。相反,每個設備都維護自己的SQLite store拷貝,並通過將修改寫入到日志文件來同步它的內容。設備與iCloud之間真正傳輸的是log file,在每個設備中,Core Data拿到log file的內容,然后使用這些內容來更新本地數據庫。當然最終的效果就是每個本地數據庫都擁有完全相同的修改。
設置Core Data store來處理iCloud,只需要你執行很少的額外工作。但是具體的步驟取決於你使用Core Data store作為中央庫(Central Library),還是為單個文檔分別創建獨立的Core Data Store。
使用Core Data管理文檔
應 用管理Core Data store為單獨的文檔時,可使用 UIManagedDocument 對象來管理單個文檔。UIManagedDocument 類自動在應用bundle中查找所有managed object model,並使用它們作為文檔數據的基礎(你也可以覆蓋 managedObjectModel 屬性自定義指定子類的object models)。由於大部分數據由managed object context處理,意味着你通常可以直接使用 UIManagedDocument 類而不需要繼承子類。UIDocumemnt的自動保存行為,能夠自動處理所有文檔的保存工作。
創建新文檔時,執行以下步驟:
- 創建 UIManagedDocument 對象
- 文檔的 persistentStoreOptions 屬性是一個Dictionary,添加一個 NSPersistentStoreUbiquitousContentNameKey 鍵,值為你標識該文檔的唯一名字。
- 添加一些初始化數據到文檔
- 使用 saveToURL:forSaveOperation:completionHandler: 方法將文檔保存到磁盤。保存文檔時,你也可以直接將它保存到iCloud;或者先保存在本地目錄,然后再移動到iCloud。保存到iCloud需使用 URLForUbiquityContainerIdentifier: 方法獲得相對iCloud的URL;如果已經保存到本地,則可以使用 setUbiquitous:itemAtURL:destinationURL:error: 方法將其移到iCloud
當 你創建一個新文檔時,Core Data創建一個file package,包含文檔的內容。這些內容有一個 DocumentMetadata.plist 文件,以及一個包含SQLite data store的目錄。除了SQLite data store(保留在本地),file package中的任何東西都會被傳輸到iCloud服務器。
打開iCloud中的現有文檔時,執行以下步驟:
- 使用 NSMetadataQuery 查找iCloud中的文檔,Metadata查找會標識你iCloud中的所有Core Data文檔。如果文檔是其它設備創建,文檔file package最初只有 DocumentMetadata.plist 一個文件。
- 打開 DocumentMetadata.plist 文件,並獲取 NSPersistentStoreUbiquitousContentNameKey 鍵的值
- 創建 UIManagedDocument 對象
- 添加 NSPersistentStoreUbiquitousContentNameKey 鍵到文檔的 persistentStoreOptions 屬性。這個鍵的值就是你在第2步中獲取的值
- 調用文檔對象的 openWithCompletionHandler: 方法來打開文檔
應 用第一次打開其它設備創建的Core Data文檔時,Core Data會自動檢測到SQLite store不存在,並在本地創建一個。然后使用 NSPersistentStoreUbiquitousContentNameKey 鍵的值(你添加到屬性的那個)來獲取適當的transaction logs,並重新構建數據庫的內容。從這時候開始,你就可以修改該文檔並保存到iCloud。你所做的修改會保存到新的log file,這樣其它設備就能將其整合到它們的SQLite store。
當應用從iCloud中 接收到文檔修改時,Core Data會自動將這些修改合並到文檔的SQLite store,並給應用發 送 NSPersistentStoreDidImportUbiquitousContentChangesNotification 通知。應用必須注冊這個通知,並使用它來刷新任何修改的記錄。如果應用不刷新本地的數據拷貝,就會將老的修改重新寫到iCloud,並產生一個沖突版本。通過及時地整合其它設備的修改,應用就能避免類似的沖突。
刪 除一個文檔時,你必須同時刪除文檔的file package,以及包含文檔transaction logs的目錄。同時刪除所有這些東西,要求你使用 NSFileCoordinator 對象來執行coordinated寫入操作。文檔的DocumentMetadata.plist 文件包含一個 NSPersistentStoreUbiquitousContentURLKey 鍵,它的值就是文檔transaction logs目錄的URL。
使用Core Data管理中央庫(Central Library)
如果應用使 用Central Core Data store來管理數據,就應該將data store直接存放在應用Sandbox目錄。使用一個Central data store的應用,通常只有一個persistent store coordinator對象和一個persistent store對象。因此,最簡單的解決辦法是將Core Data store保留在應用Sandbox,僅使用iCloud來同步修改。
在本地創建SQLite store時,執行以下步驟:
- 創 建data store時,調用 addPersistentStoreWithType:configuration:URL:options:error: 方法,並在傳遞的options Dictionary中包含 NSPersistentStoreUbiquitousContentNameKey 和 NSPersistentStoreUbiquitousContentURLKey 鍵。
- 注冊 NSPersistentStoreDidImportUbiquitousContentChangesNotification 通知,並使用它來更新所有的記錄更新。
因為你只有一個data store,你可以為 NSPersistentStoreUbiquitousContentNameKey 鍵指定任何名字。對於 NSPersistentStoreUbiquitousContentURLKey 鍵,應該指定為應用某個iCloud容 器目錄中的某個目錄URL。換句話說,這個URL應該基於 URLForUbiquityContainerIdentifier: 方法返回的URL構造而成。Core Data將修改寫入到你指定的這個目錄,其它設備則在這個目錄中查找修改。當檢測到修改時,Core Data會自動整合修改到本地的SQLite store,並通知你的應用。
同樣,你也必須及時地響應iCloud相關的修改通知。這些通知使應用能確保使用最新的數據,如果你使用老版本的數據,就可能覆蓋其它設備的新數據,並產生沖突版本。
為Core Data Transaction Logs指定自定義位置
應用Core Data Store的修改使用transaction logs來保存,這些logs存儲在用戶iCloud賬戶的一個特殊目錄中。應用的所有Core Data Stores全部使用同一個目錄來保存transaction logs。默認情況下,這個目錄的名字和應用bundle ID相同,並保存在應用默認iCloud容器目錄中。如果你已經使用這個目錄作為其它用途,你可以通過修改Core Data stores的選項來修改目錄的名字。
在 基於文檔的應用中,要自定義transaction logs目錄,必須修改每個 UIManagedDocument 對象的 persistentStoreOptions 屬性Dictionary。在字典中增加 NSPersistentStoreUbiquitousContentURLKey 鍵,並設置值為你希望使用的自定義目錄URL。這個URL需要首先使用 URLForUbiquityContainerIdentifier: 方法,並通過添加額外的路徑來擴展URL。
如果應用使用單一的Core Data store管理所有數據,在創建 persistent store時,調用 addPersistentStoreWithType:configuration:URL:options:error: 方法,並在options參數中增加 NSPersistentStoreUbiquitousContentURLKey 鍵,值也是你希望設置的目錄URL。
使用iCloud Key-Value Data Storage
應用使用iCloud Key-Value data storage來存儲參數、或小量的非關鍵配置數據。key-value data storage概念上類似於本地user defaults數據庫,應用通常用來存儲配置。區別在於iCloud數據在用戶所有設備中你的所有應用實例間共享。
使 用 NSUbiquitousKeyValueStore 類需要設置"com.apple.developer.ubiquity-kvstore-identifier" Entitlement,如果多個不同的應用配置相同的entitlement值,則這些應用都可以共享相同的key-value數據。
使用 NSUbiquitousKeyValueStore 類寫入數據到iCloud key-value store,這個類概念上也類似於 NSUserDefaults,用於保存和獲取簡單的數據類型:數字、字符串、日期、數組等等。
應 用的key-value store的容量限制為64KB(而每個鍵的限制當前也是64KB)。因此應用只能使用key-value storage記錄很少的數據,不能用於存儲用戶文檔或其它大型數據archive。典型的例子是雜志應用,可以保存用戶當前閱讀的刊物和頁數。這樣用戶 在其它設備打開相同應用時,就能回到之前閱讀的位置。
NSUbiquitousKeyValueStore 類絕對無法代替 NSUserDefaults 類,應用總是應該通過 NSUserDefaults 將所有配置數據保存在本地磁盤。然后再使用 NSUbiquitousKeyValueStore 將需要共享的數據上傳到key-value store。這樣確保iCloud不可用時,你仍然能夠訪問應用的配置數據。
負責任的iCloud App
用戶的iCloud空間有限,並且由所有應用共享。用戶可以查看指定應用消耗的iCloud空間,可以選擇刪除應用相關聯的文檔和數據。因此,應用必須對自己存儲在iCloud中的文件負責,下面是一些管理iCloud文檔的建議:
- 對存儲iCloud文檔采取一種好的策略。允許用戶啟用或禁用iCloud。
- 從用戶iCloud賬戶中刪除一個文檔,將從用戶所有計算機和設備中刪除該文檔。確保用戶明白這一點,並確認刪除操作。如果你只是想刷新文檔的本地拷貝,使用 NSFileManager 的 evictUbiquitousItemAtURL:error: 方法,而不是刪除文件。
- 存儲文檔到iCloud時,盡量將文檔存儲在"Documents"子目錄中。用戶可以單個刪除Documents目錄中的文檔以釋放空間,但是Documents目錄之外的所有東西,都被當做數據,只能一次全部刪除!
- 永遠不要存儲緩存或其它應用的私有文件到用戶的iCloud storage。用戶的iCloud賬戶只應該用於存儲用戶相關的數據,以及應用無法重新生成的內容。
- 對iCloud文件和應用Sandbox文件相同對待。保存文件應該由應用需求和保留用戶數據的需求來驅動。你不應該修改應用更頻繁或更慢地保存iCloud文件。iCloud會自動優化自己向服務器的傳輸,以確保最佳的性能。
- http://www.cocoachina.com/bbs/read.php?tid=86249&keyword=icloud