天天看點

《Core Data應用開發實踐指南》一1.1 Core Data是什麼

本節書摘來自華章出版社《core data應用開發實踐指南》一書中的第1章,第1.1節,作者 (美)tim roadley,更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視

core data是個架構,它使得開發者可以把資料當成對象來操作,而不必在乎資料在磁盤中的存儲方式。對于objective-c程式員來說,這很有用,因為他們已經可以通過代碼非常熟練地操作對象了。由core data所提供的資料對象叫做托管對象(managed object),而core data本身則位于你的應用程式和持久化存儲區(persistent store)之間。持久化存儲區是個通用的術語,指的是像sqlite資料庫、xml檔案(ios不支援用xml檔案作為持久化存儲區)或binary store(又名atomic store)這種資料檔案。由于這些檔案在底層硬體重新開機之後還會保留下來,是以它們是持久的。還有一種持久化存儲方式,它的名字非常奇怪,叫做“in-memory store”。雖說in-memory store并不是“持久的”,但開發者在用它管理資料時卻可以享受core data的所有優點,諸如變更管理與資料驗證等,另外,其效率自然也是相當高的。

為了把資料從托管對象映射到持久化存儲區中,core data需要使用托管對象模型,而開發者則可以通過對象圖(object graph)來配置應用程式的資料結構。可以把對象圖想象成一系列“餅幹模型切割刀”(cookie cutter),而托管對象正是用這些切割刀切出來的。對象圖裡的對象指的是實體,每個實體就好比一把“餅幹模型切割刀”,用于制作自定義的托管對象。有了托管對象之後,就可以直接在objective-c裡面操作它們,而無需再編寫sql代碼了(筆者假定你使用sqlite作為持久化存儲區,因為這是最常用的一種持久化存儲方式)。當把資料儲存到磁盤的時候,core data顯然會把這些托管對象映射回持久化存儲區裡面。

托管對象持有一份對持久化存儲區裡相關資料的拷貝。如果用資料庫作為持久化存儲區,那麼托管對象可能對應于資料庫裡某張資料表中的一行。如果用xml檔案作為持久化存儲區(此方式隻有mac系統支援),那麼托管對象可能對應于某個資料元素(data element)裡面的一份資料。托管對象可以是nsmanagedobject類的執行個體,但一般情況下,它都是某個nsmanagedobject子類的執行個體。這個問題将在第2章中詳細讨論。

所有托管對象都必須位于托管對象上下文(managed object context)裡面,而托管對象上下文又位于高速的易失性存儲器裡面,也就是位于ram中。為什麼需要有托管對象上下文呢?原因之一就是在磁盤與ram之間傳輸資料時會有開銷。磁盤讀寫速度比ram慢得多,是以不應該頻繁通路它。而有了托管對象上下文之後,對于原來需要讀取磁盤才能擷取到的資料,現在隻需通路這個上下文,就可以非常迅速地擷取到了。但它的缺點在于,開發者必須在托管對象上下文上面定期調用save:方法,以将變更後的資料寫回磁盤。托管對象上下文的另一個功能是記錄開發者對托管對象所做的修改,以提供完整的撤銷與重做支援。

“如果不能把一件事用簡單的話說清楚,那就表明你了解得還不夠透徹。”這是先賢阿爾伯特•愛因斯坦的一句名言。本書每章均以愛因斯坦的名言開頭。core data是個比較難學的技術,但這并不是說我們不能把它分解成多個易于了解的小知識點。筆者在編寫技術教程和文檔的時候,都會遵照愛因斯坦的教誨,盡量用比較好懂的方式把它們寫出來,同時也盡量會把内容寫得豐富一些。

圖1-1直覺地描述了core data的幾個主要概念。

《Core Data應用開發實踐指南》一1.1 Core Data是什麼

圖1-1左側的持久化存儲協調器(persistent store coordinator)裡面包含一份持久化存儲區,而存儲區裡面又含有資料表裡的若幹行資料。設定持久化存儲協調器的時候,我們通常選用sqlite資料庫作為持久化存儲區。另外,也可以選用binary、xml或in-memory等形式的持久化存儲區。但要注意,binary和xml格式的存儲區是“原子的”(atomic),也就是說,即便你隻想修改少量資料,在儲存的時候也依然需要把整個檔案都寫入磁盤。首次将原子的存儲區(atomic store)讀入記憶體時當然也會有這個問題。如果資料很多,那麼使用這種存儲區的問題就比較嚴重了,因為它會占據寶貴的記憶體空間。

與原子存儲不同,sqlite資料庫會在使用者送出變更日志時進行增量更新,變更日志也叫做事務日志。由于采用了這種更新方式,是以sqlite資料庫的記憶體占用量相對來說非常小。有鑒于此,開發者一般都會選用sqlite資料庫,尤其在把core data內建到icloud的時候,更應該如此。

持久化存儲區隻應該由core data來建立。不應該讓core data去使用不是由它所建立的資料庫。假如需要使用既有的資料,那麼應該将其導入core data。這個問題放在第8章讨論。

同一個持久化存儲協調器可以有多個持久化存儲區。把core data與icloud相內建的時候,就可能會出現這種情況。我們可以把不屬于icloud的資料放在一個存儲區裡,而把屬于icloud的資料放在另一個存儲區裡。這樣既能節省網絡帶寬,又能節省icloud存儲空間。即便你有兩個持久化存儲區,也不意味着必須使用兩種對象圖。core data的模型配置允許開發者使用多個獨立的存儲區,但卻采用同一套對象圖。在設定core data的模型配置選項時,可以指明對象圖裡的某一部分屬于哪個持久化存儲區。假如确實想使用多個持久化存儲區,那麼就不能為這些存儲區之間的資料建立“關系”了。core data的配置問題放在第15章讨論。

要想建立持久化存儲區,需生成nspersistentstore類的執行個體;要想建立持久化存儲協調器,需生成nspersistentstorecoordinator類的執行個體。

圖1-1的中部是托管對象模型,它位于持久化存儲協調器和托管對象上下文之間。顧名思義,托管對象模型是描述資料結構的模型或圖示(graphical representation),而托管對象正是以它為基礎産生出來的。它與資料庫模式(database schema)相似,有時也叫做對象圖。要想建立托管對象模型,可以用xcode來配置實體及實體之間的關系。實體類似于資料庫中的資料表模式(table schema)。實體本身并不包含資料,它們隻是規定了基于該實體的托管對象應該具有何種特性。實體就是剛才提到的那種“餅幹模型切割刀”,正如資料庫裡的資料表有字段(field)一樣,實體也有屬性(attribute)。屬性的資料類型可以是整數(integer)、字元串(string)或日期(date)。第2章與第4章将會詳述這些問題。

要想建立托管對象模型,需生成nsmanagedobjectmodel類的執行個體。

圖1-1的右側是托管對象上下文,其中包含多個托管對象。托管對象上下文負責管理其中對象的生命期(lifecycle),并且負責提供許多強大的功能,諸如faulting、變更追蹤(change tracking)、驗證(validation)等。所謂faulting,意思就是使用者從持久化存儲區中擷取資料時,系統隻會把需要用到的那一部分擷取過來。第10章将詳細讨論faulting。變更追蹤用于支援撤銷及重做功能。驗證機制用來確定由托管對象模型所訂立的規則。比方說,可以針對實體的單個屬性來限定其最小值或最大值,這将在第2章中讨論。

持久化存儲區可以有很多個,與之類似,托管對象上下文也可以不止一個。有時我們需要在背景處理任務(比方說把資料儲存到磁盤或導入資料),這種情況下可以采用多個上下文。假如在前台上下文(foreground context)上面調用save:,那麼使用者界面就可能會有“卡頓”(lag)現象,尤其當資料變化較大的時候更是如此。要想避免這個問題,有個簡單的辦法就是隻在使用者按下手機home鍵時才去調用save:,這時應用程式會轉入背景。還有個稍微複雜但卻更加靈活的辦法,就是采用兩個托管對象上下文。請記住,托管對象上下文是存放在高速記憶體裡面的。你可以配置其中一個上下文,令其把資料儲存到另一個上下文裡。一旦把前台上下文中的資料儲存到背景上下文,那麼就可将背景上下文中的資料異步地(asynchronously)存入磁盤。這種分段式的做法可以確定磁盤寫入操作不會影響使用者界面的流暢度。

從ios 5開始就可以配置多個上下文之間的上下級關系了。子上下文會将它的父上下文視為持久化存儲區,而這個父上下文實際上是用來處理各項繁重操作的(例如在背景儲存資料等)。這個問題放在第11章深入讨論。

要想建立托管對象上下文,需生成nsmanagedobjectcontext類的執行個體。