<簡書 — 劉小壯> http://www.jianshu.com/p/c0e12a897971git
`這段時間公司一直比較忙,和組裏小夥伴一塊兒把公司項目按照以前邏輯重寫了一下。因爲項目比較大,還要兼顧以前項目的迭代和其餘項目,目前爲止只寫完第一階段。
以前項目本地持久化方案主要用的是SQLite,此次重寫項目打算換一種持久化方案,因而咱們通過討論選擇了蘋果的「親兒子」CoreData。
在使用CoreData的過程當中,我也是一邊學習一邊實踐。在學習的過程當中,一些寫的質量比較高的博客對個人幫助也很大,例如objc.io等博客,在這裏就不一一列舉出來了,很是感謝這些做者。``先不說項目中用不用獲得,其實不少人都是不瞭解CoreData的,可是通過個人學習發現CoreData仍是挺不錯的。因此正如這系列文章的名字同樣-認識CoreData,打算寫這系列文章來認識一下CoreData。
這系列博客將從簡單到複雜的來說一下CoreData,其中除了基礎使用還會包括多線程、批量數據處理等內容,這些不少都是我公司項目開發過程當中接觸到的,咱們也設想了一些極端的狀況,解決方案都會體如今這系列博客中。`程序員`本人接觸CoreData時間並不長,只是專門花了一段時間學習CoreData。
本系列文章偏重於經過圖形化界面使用CoreData,不會所有采起純代碼進行CoreData的全部操做,並且那樣操做起來也確實比較麻煩,反而就失去了CoreData的優點和本質。`github
文章中若有疏漏或錯誤,還請各位及時提出,謝謝!😊
sql
在CoreData
中有一些經常使用的類,稱呼可能各不相同。因此這裏先約定一些關鍵字,以便理解後面的一些內容,這些約定不少都是出如今蘋果的官方文檔中的。NSPersistentStoreCoordinator
(Persistent Store Coordinator),縮寫爲PSC。NSManagedObjectContext
(Managed Object Context),縮寫爲MOC。NSManagedObjectModel
(Managed Object Model),縮寫爲MOM。NSManagedObject
及其子類,根據英文翻譯和其做用,稱之爲託管對象。
後綴名爲.xcdatamodeld
的文件,由於存儲着全部實體的數據結構和表示,因此稱之爲模型文件。數據庫
CoreData
出如今iOS3
中,是蘋果推出的一個數據存儲框架。CoreData
提供了一種對象關係映射(ORM
)的存儲關係,相似於Java
的hibernate框架。CoreData
能夠將OC
對象存儲到數據庫中,也能夠將數據庫中的數據轉化爲OC
對象,在這個過程當中不須要手動編寫任何SQL
語句,這是系統幫咱們完成。緩存
CoreData
最大的優點就是使用過程當中不須要編寫任何SQL
語句,CoreData
封裝了數據庫的操做過程,以及數據庫中數據和OC
對象的轉換過程。因此在使用CoreData
的過程當中,不少操做就像是對數據庫進行操做同樣,也有過濾條件、排序等操做。安全
這就至關於CoreData
完成了Model
層的大量工做,例如Model
層的表示和持久化,有效的減小了開發的工做量,使Model
層的設計更加面向對象。服務器
以前聽人說過,CoreData
比較容易入手,可是很難學精。這也是不少人說CoreData
很差用的緣由之一,只是由於使用方式有問題,或者說並無真正掌握CoreData
。數據結構
若是從性能上來講,CoreData
比SQLite
確實略差一些。可是對於移動端來講,並不須要大型網站的高併發,因此這點性能差異幾乎是沒有影響的,因此這點能夠忽略不計。在後面的文章中,將會給出CoreData
的優勢和缺點對比,以及詳細的性能測評。多線程
託管對象上下文,進行數據操做時大多都是和這個類打交道。
託管對象模型,一個託管對象模型關聯一個模型文件(.xcdatamodeld
),存儲着數據庫的數據結構。
持久化存儲協調器,負責協調存儲區和上下文之間的關係。
託管對象類,全部CoreData
中的託管對象都必須繼承自當前類,根據實體建立託管對象類文件。
1.1 建立模型文件,後綴名爲.xcdatamodeld
。建立模型文件以後,能夠在其內部進行添加實體等操做(用於表示數據庫文件的數據結構)
1.2 添加實體(表示數據庫文件中的表結構),添加實體後須要經過實體,來建立託管對象類文件。
1.3 添加屬性並設置類型,能夠在屬性的右側面板中設置默認值等選項。(每種數據類型設置選項是不一樣的)
1.4 建立獲取請求模板、設置配置模板等。
1.5 根據指定實體,建立託管對象類文件(基於NSManagedObject
的類文件)
2.1 建立託管對象上下文(NSManagedObjectContext
)
2.2 建立託管對象模型(NSManagedObjectModel
)
2.3 根據託管對象模型,建立持久化存儲協調器(NSPersistentStoreCoordinator
)
2.4 關聯並建立本地數據庫文件,並返回持久化存儲對象(NSPersistentStore
)
2.5 將持久化存儲協調器賦值給託管對象上下文,完成基本建立。
以前看到過幾張介紹CoreData
結構的圖片,感受其表示的結構比較清晰。能夠經過這幾張圖片初步認識一下CoreData
,在後面的文章中還會對這幾個類進行詳細解釋。
上圖中是初始化MOC
所涉及到的一些類,由這些類實例化並最終構成可使用的MOC
。圖中編號是實例化一個具有數據處理能力的MOC
過程,這個過程和上面介紹過的實例化上下文對象相同。
在PSC
建立並關聯本地數據庫,並設置爲MOC
的persistentStoreCoordinator
屬性後,MOC
就具有對當前存儲區全部託管對象操做的能力。可是須要注意的是,MOC
對託管對象是懶加載的,在使用時纔會被加載到MOC
的緩存中。
MOM
對象加載模型文件後,獲取到模型文件中全部實體的構成結構。因爲MOM
中存儲着模型文件的結構,PSC
須要經過MOM
對象實例化本地數據庫。
全部屬性都存在Entity
中,以及有關聯關係的屬性和請求模板,這都會在後面的章節中講到。
能夠經過Entity
建立繼承自NSManagedObject
類的文件,這個文件就是開發中使用的託管對象,具有模型對象的表示功能,CoreData
的本地持久化都是經過這個類及其子類完成的。
在CoreData
的總體結構中,主要分爲兩部分。一個是NSManagedObjectContext
管理的模型部分,管理着全部CoreData
的託管對象。一個是SQLite
實現的本地持久化部分,負責和SQL
數據庫進行數據交互,主要由NSPersistentStore
類操做。這就構成了CoreData
的大致結構。
從圖中能夠看出,這兩部分都是比較獨立的,兩部分的交互由一個持久化存儲調度器(NSPersistentStoreCoordinator
)來控制。上層NSManagedObjectContext
存儲的數據都是交給持久化調度器,由調度器調用具體的持久化存儲對象(NSPersistentStore
)來操做對應的數據庫文件,NSPersistentStore
負責存儲的實現細節。這樣就很好的將兩部分實現了分離。
對於CoreData
的總體結構,由於CoreData
底層存儲原本就是用SQLite
實現的,因此我用CoreData
的結構和SQLite
對比了一下,發現仍是不少類似之處的。
.xcdatamodeld
文件表明着數據庫文件結構,經過.xcdatamodeld
編譯後的.momd
文件生成數據庫。每一個實體表明一張數據表,實體之間的關聯關係就是SQLite
的外鍵。
下圖就是CoreData
底層存儲的結構,用紅圈圈住的部分指向關聯表的主鍵下標。例如1
就指向關聯表的主鍵下標爲1
的行。
CoreData
本質仍是使用SQLite
進行存儲,並無另外提供加密功能,具體的數據加解密還須要本身完成。
CoreData在硬盤上的數據存儲結構:
經過PSC
指定建立SQLite
目錄後,會在指定的目錄下生成一個數據庫文件,同時還會生成兩個同名但後綴不一樣的文件,其中只有後綴.sqlite
的文件是存儲數據的文件。
這個數據庫文件中會默認生成三個表,Z_METADATA
、Z_PRIMARYKEY
、Z_MODELCACHE
,其餘咱們本身的表也都是大寫Z開頭的。
在每一個表中,系統還會默認生成三個字段,Z_PK
、Z_ENT
、Z_OPT
三個字段,也都是大寫Z開頭而且帶下劃線的。其餘字段就是咱們本身的字段了,大寫Z開頭但不帶下劃線。
如今市面上的大多數項目,都是使用SQLite
做爲持久化的方案,而CoreData
的使用並非很廣泛。對於這個問題,我認爲首先是不少項目開始的比較早,那時候好多iOS
程序員都是從其餘語言轉過來的,更加熟悉SQLite
,因此用SQLite
比較多一些。後面若是不進行大的項目重構,就很難換其餘的持久化方案了。
還有就是不熟悉CoreData
,也不想去了解和深刻學習CoreData
,我認爲這是很大的緣由。因此項目中用CoreData
的人並很少,而真正掌握CoreData
技術的人更少。
以前聽其餘人說CoreData
的執行效率不如SQLite
高,這個若是深究的話,確實CoreData
要比SQLite
效率差一些,只不過並無太大區別。CoreData
本質也是在底層執行SQL
語句,只是CoreData
的SQL
語句執行邏輯比較耗時,沒有手動編寫SQL
語句更加直接。咱們能夠將CoreData
的調試功能打開,具體看一下SQL
語句的執行。
這裏要說一點,客戶端畢竟不是服務端,不須要像服務器那樣大量的數據查詢,因此CoreData
是徹底能夠應對客戶端的查詢量的。若是從靈活性來講,CoreData
確實沒有SQLite
的靈活性高,一些SQLite
的複雜功能可能也不能實現,可是就目前大多數項目來講,CoreData
已經可以知足項目持久化需求了。
致使執行效率差別的緣由還體如今對象轉換上,CoreData
在執行SQL
語句的基礎上,還多了一層將數據映射給託管對象的操做,這樣獲得的就是OC
的託管對象,而SQLite
獲得的則不是。若是給SQLite
執行完成後,也加一層建立託管對象並賦值的操做,這時候對比性能二者的差距可能就會更小了。
下面是一篇關於CoreData
、FMDB
、Realm
性能測試結果的博客,最後的結果我也沒有去驗證,只是大體看了一下代碼仍是比價靠譜的。做者測試Demo和原文地址。
測試數據的數量是以K爲單位,最少爲1K的數據量。涉及到的操做主要是下面四種:
1K
條數據。1K
條數據。10K
條數據,連續查詢單次爲1K
數據。10K
條數據總量,更新其中1K
條數據的部分字段性能。根據測試結果能夠發現,在前面兩種插入操做,CoreData
的性能比FMDB
和Realm
要快不少。
而對於查詢操做,CoreData
比其餘兩種操做耗時多不少,大概多出三四倍。這極可能和CoreData
將查詢結果的數據轉爲託管對象有關係,拋去CoreData
這部分轉換操做性能會比如今好不少。
而更新操做則直接基於SQLite
封裝的FMDB
有絕對的優點,FMDB
和其餘兩種操做差距大概是十倍左右,而其餘兩種操做性能差很少。固然CoreData
也存在着上面提到的對象轉換操做,CoreData
拋去這步結果可能會比如今好不少。
下面的測試數據中,取得是三次測試結果的平均值。
第三方 | 編號 |
---|---|
CoreData | 1 |
FMDB | 2 |
Realm | 3 |
CoreData
本質上是對SQLite
的一個封裝,在內部將對象的持久化轉化爲SQL
語句執行,能夠在項目中將CoreData
調試打開,從而能夠看到CoreData
的SQL
語句執行和一些其餘log
信息。
Product
,選擇Edit Scheme
.Arguments
,在下面的ArgumentsPassed On Launch
中添加下面兩個選項。-com.apple.CoreData.SQLDebug
1
若是是在模擬器上調試程序,能夠經過 sqlite3 /數據庫路徑/
命令來查看和操做數據庫。.tables
查看當前數據庫文件中全部的表名select *from tableName
執行查詢的SQL
語句
好多同窗都問我有Demo
沒有,其實文章中貼出的代碼組合起來就是個Demo
。後來想了想,仍是給本系列文章配了一個簡單的Demo
,方便你們運行調試,後續會給全部博客的文章都加上Demo
。
Demo
只是來輔助讀者更好的理解文章中的內容,應該博客結合Demo
一塊兒學習,只看Demo
仍是不能理解更深層的原理。Demo
中幾乎每一行代碼都會有註釋,各位能夠打斷點跟着Demo
執行流程走一遍,看看各個階段變量的值。
Demo地址:劉小壯的Github
這兩天更新了一下文章,將CoreData
系列的六篇文章整合在一塊兒,作了一個PDF
版的《CoreData Book》,放在我Github上了。PDF
上有文章目錄,方便閱讀。
若是你以爲不錯,請把PDF幫忙轉到其餘羣裏,或者你的朋友,讓更多的人瞭解CoreData,衷心感謝!😁