原文出處: http://chengway.in/post/ji-zhu/core-data-by-tutorials-bi-ji-wu
我們繼續(xù)來看《Core Data by Tutorials》這本書的第七章 Syncing with iCloud,本章所討論的是iOS 8和Yosemite最新釋出的iCloud Drive,至于iCloud Drive與iCloud的區(qū)別可以看這里,調(diào)試本章code需要一個開發(fā)者帳號:)
iCloud是基于Core Data的,之前幾個版本確實做的比較爛,不過蘋果也在不斷地改進。本章的代碼其實就是在第六章代碼的基礎(chǔ)上改為Cloud版本。
iCloud對core data store同步其實使用的是ubiquity containers(無處不在的容器),這個無處不在的容器存在你應(yīng)用的sandbox中,并由iOS系統(tǒng)替你管理。如同向NSFileManager請求應(yīng)用的 Documents directory,對于iCloud來說,請求的是一個ubiquity container URL。
Core Data通過這個ubiquity container URL保存應(yīng)用程序的數(shù)據(jù),他和通過URL保存到Documents沒什么區(qū)別。唯一不同的就是iCloud后臺進程監(jiān)視著ubiquity container里面文件的變化,時刻準備上傳到云端,而這一切都是系統(tǒng)自動完成的。
這里需要注意的是,iCloud的運行機制有點類似與Git,每次同步的其實是transaction logs,而不是data store本身。而與Git不同的是,commit的時候,Git經(jīng)常需要處理沖突。但iCloud的commit change是“atomic”的,意味著,要么數(shù)據(jù)全部有效,要么全部丟棄。
作者這里用倫敦橋搬家舉了一個很形象的例子,把橋拆成一磚一磚,然后搬到目的地再按照log記錄的正確順序重組。iCloud的工作機制也差不多。
在Xcode中將Capabilities中的iCloud啟用。這里可以使用默認的ubiquity container,也可以自定義。
為.addPersistentStoreWithType方法的參數(shù)**option數(shù)組增加一個成員NSPersistentStoreUbiquitousContentNameKey**,同樣地在stack的初始化中設(shè)置。
lazy var stack : CoreDataStack = {
let options = [NSPersistentStoreUbiquitousContentNameKey: "CloudNotes",
NSMigratePersistentStoresAutomaticallyOption: true,
NSInferMappingModelAutomaticallyOption: true]
let stack = CoreDataStack(modelName: "CloudNotesDataModel",
storeName: "CloudNotes",
options: options)
return stack
}()
使用NSPersistentStoreUbiquitousContentNameKey的值CloudNotes,在ubiquity container中來唯一標識該應(yīng)用的persistent store。
到此為止,已經(jīng)為該APP完全開啟了iCloud同步,很簡單吧。但Core Data在背后還是做了一些工作的,其中一項就是設(shè)置了一個fallback store,用于在iCloud離線時保存數(shù)據(jù)。不過開發(fā)者完全不用擔(dān)心這些東西。
至于測試則需要擁有一個開發(fā)者帳號,登錄itunesconnect,依次選擇Users and Roles?>>?Sandbox Testers?新建一個測試用戶,這里注意的是,新建完的測試帳號需要在真機設(shè)備上激活一下。
具體的測試也很簡單,現(xiàn)在模擬器上運行起來,可以看到目前所有添加的數(shù)據(jù),然后切換target device(并不按下停止鍵)選擇真機設(shè)備Run一下,此時模擬器和真機會同時運行。此時在模擬器上創(chuàng)建新的記錄,并選擇Debug\Trigger iCloud Sync來觸發(fā)同步,不久應(yīng)該就能看到新添加的記錄在真機上出現(xiàn)。作者還展示了iCloud gauge的方式來查看具體的同步記錄。
現(xiàn)在可以來總結(jié)一下設(shè)置iCloud的基本步驟了,主要有三步:
前兩步已經(jīng)說過了,現(xiàn)在來看第3點。
該實例程序使用的是fetched results controller,而fetched results controller主要又依賴的是NSManagedObjectContext。但是iCloud更新是直接在persistent store級別的,不會經(jīng)過Context。因此也不會觸發(fā)fetched results controller的代理方法來更新UI。
既然如此,我們需要知道iCloud何時更新可以通過監(jiān)聽廣播的方法來實現(xiàn),通過監(jiān)聽NSPersistentStoreDidImportUbiquitousContentChangesNotification廣播,來刷新context(通過mergeChangesFromContextDidSaveNotification(notification))
當(dāng)前賬戶登出的話,Core Data會刪除當(dāng)前數(shù)據(jù)(都安全保存在云端,會在用戶重新登錄時同步回來)。帳號切換時,Core Data會發(fā)送如下兩個通知:
the notification會包含具體要被adding/added或removing/removed的NSPersistentStore objects
先處理 “will change” notification:
func persistentStoreCoordinatorWillChangeStores( notification: NSNotification){
var error : NSErrorPointer = nil if context.hasChanges {
if context.save(error) == false {
print("Error saving \(error)")
}
}
context.reset()
}
再處理“did change” notification
func persistentStoreCoordinatorDidChangeStores(notification:NSNotification){
notes.performFetch(nil)
tableView.reload()
}
更多建議: