本節書摘來自異步社群《ios元件與架構——ios sdk進階特性剖析》一書中的第8章,第8.4節與icloud互動,作者 【美】kyle richter , joe keeley,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視
8.4 與icloud互動
ios元件與架構——ios sdk進階特性剖析
添加icloud功能後,應用需要處理一些額外的複雜問題。應用未使用icloud時,列出其文檔很簡單,但使用icloud後,可用文檔清單随時會變,甚至在清單生成和顯示期間都會改變。另外,由于可能在多台裝置上同時編輯同一個文檔,可能導緻不使用icloud時根本不會出現的沖突。本節介紹如何妥善地處理這些問題。
8.4.1 列出icloud中的文檔
要顯示可用的備忘錄清單,示例應用需要查詢icloud目錄,以确定那裡都有哪些檔案。這是使用nsmetadataquery完成的。

将nsmetadataquery的搜尋範圍設定成了nsmetadataqueryubiquitousdocumentsscope,它表示應用的icloud目錄。接下來,将謂詞指定為一個檔案模式字元串,這個字元串與檔案擴充名為.icfnote的文檔都比對。中繼資料查詢是在icfmasterviewcontroller的viewdidload方法中執行的,這個視圖控制器還接收來自nsmetadataquery的通知。
這兩個通知分别在如下兩種情況下調用方法processfiles::nsmetadataquery收集了與謂詞比對的資訊;其他裝置修改了icloud中的文檔。icloud同步來自其他裝置的新檔案時,将更新icloud目錄。
調用processfiles:後,在處理結果期間讓nsmetadataquery停止收集資訊很重要。這可避免這個方法在更新期間被再次調用,以免應用崩潰或獲得錯誤的結果。然後,可疊代查詢結果并建立新的備忘錄清單。建立備忘錄清單後,再更新表視圖,如圖8.4所示。接下來,讓nsmetadataquery繼續擷取檔案系統更新。
nsmetadataquery生成的檔案清單是一個nsurl數組。在方法tableview:cell forrowatindexpath:中,從這些nsurl中提取了檔案名(不包括擴充名),以便将其顯示在表單元格中。
其中的if邏輯檢查備忘錄是不是最後更新的備忘錄,這種資訊是使用icloud鍵值存儲維護的,這将在本章後面介紹(參見8.6節)。如果是,就在檔案名前面加上一個星号。
打開文檔和建立文檔在8.3.2節介紹過。使用者選擇一個表行或輕按加号按鈕時,将把新文檔或既有文檔的url傳遞給詳細視圖控制器,後者打開或建立指定的文檔,在文本視圖中顯示該文檔的文本,并将文本視圖設定為第一響應者,讓使用者馬上能夠進行編輯。
關閉文檔很簡單。在詳細視圖控制器的方法viewwilldisappear:中,使用文本視圖中的文本更新文檔,再關閉文檔。由于啟用了自動儲存功能,是以儲存是自動完成的。
8.4.2 檢測icloud沖突
所有的同步技術都可能發生沖突。沖突指的是文檔在多台裝置上被同時編輯,導緻icloud根據同步規則無法确定哪個版本是最新的。
要引發沖突,可在兩台裝置上同時運作示例應用。将一台裝置切換到飛行模式,編輯并儲存一份備忘錄;再在另一台裝置上編輯并儲存這份備忘錄。然後,在第一台裝置上關閉飛行模式,并嘗試在第二台裝置上再次編輯那份備忘錄。第二台裝置将發生沖突。
uidocument類有一個文檔狀态屬性,指出了文檔發生了沖突還是可正常編輯。uidocument對象還在文檔狀态發生變化時發出通知,這很有用,因為編輯文檔期間發生沖突時,如果能夠馬上獲悉并解決沖突,使用者體驗将好得多。為檢測沖突,詳細視圖控制器需要通過注冊從文檔那裡收到文檔狀态變化通知,這是在方法viewwillappear: 中完成的。
如果文檔狀态為uidocumentstateeditingdisabled,這個方法就讓文本視圖放棄第一響應者地位,導緻編輯馬上結束。如果文檔狀态為uidocumentstateinconflict,就更新使用者界面,顯示一個讓使用者能夠通過輕按來解決沖突的按鈕(如圖8.5所示),否則就讓使用者界面傳回到正常編輯狀态。