原文出處: 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需要一個(gè)開發(fā)者帳號(hào):)
iCloud是基于Core Data的,之前幾個(gè)版本確實(shí)做的比較爛,不過蘋果也在不斷地改進(jìn)。本章的代碼其實(shí)就是在第六章代碼的基礎(chǔ)上改為Cloud版本。
iCloud對(duì)core data store同步其實(shí)使用的是ubiquity containers(無處不在的容器),這個(gè)無處不在的容器存在你應(yīng)用的sandbox中,并由iOS系統(tǒng)替你管理。如同向NSFileManager請(qǐng)求應(yīng)用的 Documents directory,對(duì)于iCloud來說,請(qǐng)求的是一個(gè)ubiquity container URL。
Core Data通過這個(gè)ubiquity container URL保存應(yīng)用程序的數(shù)據(jù),他和通過URL保存到Documents沒什么區(qū)別。唯一不同的就是iCloud后臺(tái)進(jìn)程監(jiān)視著ubiquity container里面文件的變化,時(shí)刻準(zhǔn)備上傳到云端,而這一切都是系統(tǒng)自動(dòng)完成的。
這里需要注意的是,iCloud的運(yùn)行機(jī)制有點(diǎn)類似與Git,每次同步的其實(shí)是transaction logs,而不是data store本身。而與Git不同的是,commit的時(shí)候,Git經(jīng)常需要處理沖突。但iCloud的commit change是“atomic”的,意味著,要么數(shù)據(jù)全部有效,要么全部丟棄。
作者這里用倫敦橋搬家舉了一個(gè)很形象的例子,把橋拆成一磚一磚,然后搬到目的地再按照log記錄的正確順序重組。iCloud的工作機(jī)制也差不多。
在Xcode中將Capabilities中的iCloud啟用。這里可以使用默認(rèn)的ubiquity container,也可以自定義。
為.addPersistentStoreWithType方法的參數(shù)**option數(shù)組增加一個(gè)成員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中來唯一標(biāo)識(shí)該應(yīng)用的persistent store。
到此為止,已經(jīng)為該APP完全開啟了iCloud同步,很簡(jiǎn)單吧。但Core Data在背后還是做了一些工作的,其中一項(xiàng)就是設(shè)置了一個(gè)fallback store,用于在iCloud離線時(shí)保存數(shù)據(jù)。不過開發(fā)者完全不用擔(dān)心這些東西。
至于測(cè)試則需要擁有一個(gè)開發(fā)者帳號(hào),登錄itunesconnect,依次選擇Users and Roles?>>?Sandbox Testers?新建一個(gè)測(cè)試用戶,這里注意的是,新建完的測(cè)試帳號(hào)需要在真機(jī)設(shè)備上激活一下。
具體的測(cè)試也很簡(jiǎn)單,現(xiàn)在模擬器上運(yùn)行起來,可以看到目前所有添加的數(shù)據(jù),然后切換target device(并不按下停止鍵)選擇真機(jī)設(shè)備Run一下,此時(shí)模擬器和真機(jī)會(huì)同時(shí)運(yùn)行。此時(shí)在模擬器上創(chuàng)建新的記錄,并選擇Debug\Trigger iCloud Sync來觸發(fā)同步,不久應(yīng)該就能看到新添加的記錄在真機(jī)上出現(xiàn)。作者還展示了iCloud gauge的方式來查看具體的同步記錄。
現(xiàn)在可以來總結(jié)一下設(shè)置iCloud的基本步驟了,主要有三步:
前兩步已經(jīng)說過了,現(xiàn)在來看第3點(diǎn)。
該實(shí)例程序使用的是fetched results controller,而fetched results controller主要又依賴的是NSManagedObjectContext。但是iCloud更新是直接在persistent store級(jí)別的,不會(huì)經(jīng)過Context。因此也不會(huì)觸發(fā)fetched results controller的代理方法來更新UI。
既然如此,我們需要知道iCloud何時(shí)更新可以通過監(jiān)聽廣播的方法來實(shí)現(xiàn),通過監(jiān)聽NSPersistentStoreDidImportUbiquitousContentChangesNotification廣播,來刷新context(通過mergeChangesFromContextDidSaveNotification(notification))
當(dāng)前賬戶登出的話,Core Data會(huì)刪除當(dāng)前數(shù)據(jù)(都安全保存在云端,會(huì)在用戶重新登錄時(shí)同步回來)。帳號(hào)切換時(shí),Core Data會(huì)發(fā)送如下兩個(gè)通知:
the notification會(huì)包含具體要被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()
}
更多建議: