iCloud Storage 詳細的官方文檔

官方地址: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:

  1. 選擇應用的target
  2. 選擇Summary
  3. 在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

  1. 在應用Sandbox中創建本地文件或目錄。使用的時候,必須由file presenter來管理文件或目錄。如UIDocument
  2. 使用  URLForUbiquityContainerIdentifier: 方法獲取iCloud容器目錄的URL
  3. 使用容器目錄URL來構建一個新的URL,指定文件或目錄在iCloud中的存儲位置
  4. 調用 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 對象來管理,可以通過類方法來獲取。

解決衝突:

  1. 使用類方法 currentVersionOfItemAtURL: 獲取當前文件版本
  2. 使用類方法 unresolvedConflictVersionsOfItemAtURL: 獲取所有衝突版本的數組
  3. 對每個file version對象,執行以下任何動作來解決衝突:[list=1]
  4. 如果實際可行的話,合併衝突文件修改的數據
  5. 如果能夠安全地執行而不丟失數據的話,忽略某個衝突版本
  6. 提示用戶選擇保留哪個版本的文件(當前文件或衝突文件),這是最後的選擇。

更新當前文件:

  1. 如果當前文件勝利(winner),不需要更新當前文件
  2. 如果某個衝突版本勝利(winner),使用 coordinated write 操作,以衝突版本的文件內容覆蓋當前文件
  3. 如果用戶選擇保存衝突版本爲另一個名字,以該衝突版本的內容創建一個新文件

設置所有衝突版本對象的 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的自動保存行爲,能夠自動處理所有文檔的保存工作。


創建新文檔時,執行以下步驟:

  1. 創建 UIManagedDocument 對象
  2. 文檔的 persistentStoreOptions 屬性是一個Dictionary,添加一個 NSPersistentStoreUbiquitousContentNameKey 鍵,值爲你標識該文檔的唯一名字。
  3. 添加一些初始化數據到文檔
  4. 使用 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中的現有文檔時,執行以下步驟:

  1. 使用 NSMetadataQuery 查找iCloud中的文檔,Metadata查找會標識你iCloud中的所有Core Data文檔。如果文檔是其它設備創建,文檔file package最初只有 DocumentMetadata.plist 一個文件。
  2. 打開 DocumentMetadata.plist 文件,並獲取 NSPersistentStoreUbiquitousContentNameKey 鍵的值
  3. 創建 UIManagedDocument 對象
  4. 添加 NSPersistentStoreUbiquitousContentNameKey 鍵到文檔的 persistentStoreOptions 屬性。這個鍵的值就是你在第2步中獲取的值
  5. 調用文檔對象的 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時,執行以下步驟:

  1. 創 建data store時,調用 addPersistentStoreWithType:configuration:URL:options:error: 方法,並在傳遞的options Dictionary中包含 NSPersistentStoreUbiquitousContentNameKey 和 NSPersistentStoreUbiquitousContentURLKey 鍵。
  2. 註冊 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會自動優化自己向服務器的傳輸,以確保最佳的性能。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章