<簡書 — 劉小壯> http://www.jianshu.com/p/61b7a615508cios
到目前爲止,已經將
CoreData
相關的知識點都講完了。git在這篇文章中,主要講一個
CoreData
第三方庫-MagicalRecord
。目前爲止這個第三方在Github
上有**9500+**的Star
,是全部CoreData
第三方庫中使用最多、功能最全的。在文章的後面還會對CoreData
作一個總結,以及對本系列全部文章作一個總結。github文章中若有疏漏或錯誤,還請各位及時提出,謝謝!數據庫
CoreData
是蘋果自家推出的一個持久化框架,使用起來更加面向對象。可是在使用過程當中會出現大量代碼,並且CoreData
學習曲線比較陡峭,若是掌握很差,在使用過程當中很容易形成其餘問題。編程
國外開發者開源了一個基於CoreData
封裝的第三方——MagicalRecord
,就像是FMDB
封裝SQLite
同樣,MagicalRecord
封裝的CoreData
,使得原生的CoreData
更加容易使用。而且MagicalRecord
下降了CoreData
的使用門檻,不用去手動管理以前的PSC
、MOC
等對象。數據結構
根據Github
上MagicalRecord
的官方文檔,MagicalRecord
的優勢主要有三條:併發
1. 清理項目中CoreData
代碼 2. 支持清晰、簡單、一行式的查詢操做 3. 當須要優化請求時,能夠獲取NSFetchRequest
進行修改app
將MagicalRecord
添加到項目中,和使用其餘第三方同樣,能夠經過下載源碼和CocoaPods
兩種方式添加。框架
1. 從Github下載MagicalRecord源碼,將源碼直接拖到項目中,後續須要手動更新源碼。性能
2. 也能夠經過CocoaPods
安裝MagicalRecord
,須要在Podfile
中加入下面命令,後續只須要經過命令來更新。
pod "MagicalRecord"
在以前建立新項目時,經過勾選"Use Core Data"
的方式添加CoreData
到項目中,會在AppDelegate
文件中生成大量CoreData
相關代碼。若是是大型項目,被佔用的位置是很重要的。而對於MagicalRecord
來講,只須要兩行代碼便可。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 初始化CoreData堆棧,也能夠指定初始化某個CoreData堆棧 [MagicalRecord setupCoreDataStack]; return YES; } - (void)applicationWillTerminate:(UIApplication *)application { // 在應用退出時,應該調用cleanUp方法 [MagicalRecord cleanUp]; }
MagicalRecord
是支持CoreData
的.xcdatamodeld
文件的,使得CoreData
這一優勢能夠繼續使用。創建數據結構時仍是像以前使用CoreData
同樣,經過.xcdatamodeld
文件的方式創建。
CoreData
是支持iCloud
的,MagicalRecord
對iCloud
相關的操做也作了封裝,只須要使用MagicalRecord+iCloud.h
類中提供的方法,就能夠進行iCloud
相關的操做。
例以下面是MagicalRecord+iCloud.h
中的一個方法,須要將相關參數傳入便可。
+ (void)setupCoreDataStackWithiCloudContainer:(NSString *)containerID localStoreNamed:(NSString *)localStore;
MagicalRecord
對上下文的管理和建立也比較全面,下面是MagicalRecord
提供的部分建立和獲取上下文的代碼。由於是給NSManagedObjectContext
添加的Category
,能夠直接用NSManagedObjectContext
類調用,使用很是方便。
可是須要注意,雖然系統幫咱們管理了上下文對象,對於耗時操做仍然要放在後臺線程中處理,而且在主線程中進行UI操做。
+ [NSManagedObjectContext MR_context] 設置默認的上下文爲它的父級上下文,併發類型爲NSPrivateQueueConcurrencyType + [NSManagedObjectContext MR_newMainQueueContext] 建立一個新的上下文,併發類型爲NSMainQueueConcurrencyType + [NSManagedObjectContext MR_newPrivateQueueContext] 建立一個新的上下文,併發類型爲NSPrivateQueueConcurrencyType + [NSManagedObjectContext MR_contextWithParent:] 建立一個新的上下文,容許自定義父級上下文,併發類型爲NSPrivateQueueConcurrencyType + [NSManagedObjectContext MR_contextWithStoreCoordinator:] 建立一個新的上下文,並容許自定義持久化存儲協調器,併發類型爲NSPrivateQueueConcurrencyType + [NSManagedObjectContext MR_defaultContext] 獲取默認上下文對象,項目中最基礎的上下文對象,併發類型是NSMainQueueConcurrencyType
MagicalRecord
對NSManagedObject
添加了一個Category
,將增刪改查等操做放在這個Category
中,使得這些操做能夠直接被NSManagedObject
類及其子類調用。
.1. 增 對於託管模型的建立很是簡單,不須要像以前還須要進行上下文的操做,如今這都是MagicalRecord
幫咱們完成的。
// 建立並插入到上下文中 Employee *emp = [Employee MR_createEntity];
.2. 刪
// 從上下文中刪除當前對象 [emp MR_deleteEntity];
.3. 改
// 獲取一個上下文對象 NSManagedObjectContext *defaultContext = [NSManagedObjectContext MR_defaultContext]; // 在當前上下文環境中建立一個新的Employee對象 Employee *emp = [Employee MR_createEntityInContext:defaultContext]; emp.name = @"lxz"; emp.brithday = [NSDate date]; emp.height = @1.7; // 保存修改到當前上下文中 [defaultContext MR_saveToPersistentStoreAndWait];
.4. 查
// 執行查找操做,並設置排序條件 NSArray *empSorted = [Employee MR_findAllSortedBy:@"height" ascending:YES];
下面示例代碼中,Employee
根據已有的employeeFilter
謂詞對象,建立了employeeRequest
請求對象,並將請求對象作修改後,從MOC
中獲取請求結果,實現自定義查找條件。
NSPredicate *employeeFilter = [NSPredicate predicateWithFormat:@"name LIKE %@", @"*lxz*"]; NSFetchRequest *employeeRequest = [Employee MR_requestAllWithPredicate:employeeFilter]; employeeRequest.fetchOffset = 10; employeeRequest.fetchLimit = 10; NSArray *employees = [Employee MR_executeFetchRequest:employeeRequest];
.1. 能夠經過修改MR_LOGGING_DISABLED
預編譯指令的值,控制log
打印。
#define MR_LOGGING_DISABLED 1
.2.MagicalRecord
在DEBUG
模式下,對模型文件發生了更改,而且沒有建立新的模型文件版本。MagicalRecord
默認會將舊的持久化存儲刪除,建立新的持久化存儲。
MagicalRecord
的使用方法還有不少,這裏只是將一些比較經常使用的拿出來說講,其餘就不一一講解了。在Github
上有國人翻譯的MagicalRecord
官方文檔,翻譯的很是全面,並且是實時更新的。
這篇文章關於MagicalRecord
的部分,也是參考文章來寫的,我這裏就犯了個懶。。。
不管是什麼東西,確定不會是絕對完美的,CoreData
也是如此。CoreData
被設計出來後,對比其餘本地持久化方案有本身獨有的優點,也有比較嚴重的問題。
對於一個本地持久化方案的選取,仍是要根據公司業務需求,來選擇一個適合項目的方案,並無哪一個方案是萬能的。
能夠設置關聯關係,也就是以前講過的關聯屬性,關聯屬性能夠和當前對象一塊兒被MOC
操做。 例如Company
關聯一個Person
對象,對Company
進行操做時,也能夠經過點語法從Company
中獲取Person
,Person
的修改會隨着Company
一塊兒被持久化。 若是用SQLite
實現起來是很麻煩的,但CoreData
能夠很容易的完成,這也是CoreData
更加面向對象的一種體現。
更加面向對象,將以前Model
層的表示和持久化合二爲一。把數據庫的交互和對象的轉換封裝起來,使用時不須要接觸到任何SQLite
相關的代碼,直接使用託管對象便可。
開發效率比較快,能夠很快的封裝一個基於CoreData
實現的Model
層,而不須要太多的代碼就能夠實現。
能夠很好的防範SQL注入
的問題。對於SQLite
來講,若是是用FMDB
而且用?佔位符
,也能夠防範SQL注入
的問題。
可視化化效果好且結構清晰。將模型文件內部的結構,以及實體之間的對應關係等,以可視化的結構展示出來。
對OC
原生編程支持很是好,支持keyPath
操做方式。例如設置NSPredicate
查找條件時,可使用keyPath
的點語法設置屬性。而其餘持久化存儲對於這點支持的不太好,須要編寫很複雜的查找條件,看起來也不太好理解。 畢竟是Apple
自家推出的,因此對OC
融合度比較高,能夠很好的配合和使用OC
對象。
設置一對一或一對多的關係,設置關係後作存儲和查詢也很是方便,這是很是便於開發的。若是對於性能沒有苛刻的要求,而且持久化對象之間關係比較複雜,比較推薦使用CoreData
。
靈活性不如SQLite
,CoreData
是對SQLite
的一個封裝,上層不能直接對數據庫進行操做。處理任何數據都要按照CoreData
內部的實現邏輯執行,而不能自定義執行邏輯,對執行邏輯沒有可控性。
進行大量數據處理時比較吃力,性能明顯低於直接操做SQLite
數據庫,並且內存佔用很是大,須要手動作內存控制。 當執行一個操做時涉及的數據比較多,須要將全部相關的託管對象加載到內存中,並且中間還涉及到對象的轉換等操做。這樣對性能和內存的消耗都是很是大的,和涉及到的數據量成正比。
由於CoreData
底層是用SQLite
實現的,能夠在CoreData
的基礎上,直接編寫SQL語句
對數據庫進行操做。可是並不推薦這樣作,在一個項目中應該只有一種持久化的主體方案。並且若是這兩種方式混用的話,對於後期維護是很是困難的。 若是出現這樣的需求,最好直接去用SQLite。
CoreData入門門檻比較高,很難很好的掌握。 不少人都說CoreData
很差用,這個緣由很大一部分都是由於使用方式的問題。CoreData
框架學習難度比較大,致使不少人都只是簡單的使用CoreData
,這些用法不少都是不合理的,不少的高級用法並無用到。
到目前爲止CoreData
系列的六篇文章就都寫完了,文章中可能存在一些沒有注意的問題,還請各位提出。博客中包括CoreData
在內的全部文章永久更新維護,會不斷將新知識添加到對應的文章中,也會對落後的文章進行重寫。
在第一篇文章中也說到,我接觸CoreData
時間也不是很長,這系列文章更像是我學習的一個總結。可是我確實是很認真的在寫,文章內容也是檢查了不少遍,防止錯字或者語法問題。知識點總結的仍是比較全面的,在後續我還會更深刻的學習CoreData
,也可能會推出後續文章。
許多人對於CoreData
有不少意見,認爲CoreData
有各類各樣的問題,這並非空穴來風。在我學習CoreData
的過程當中,也發現CoreData
確實存在諸多問題,例如查詢性能略差、靈活性等。因此在使用CoreData
的時候,仍是根據公司業務需求來權衡是否使用CoreData
。
好多同窗都問我有Demo
沒有,其實文章中貼出的代碼組合起來就是個Demo
。後來想了想,仍是給本系列文章配了一個簡單的Demo
,方便你們運行調試,後續會給全部博客的文章都加上Demo
。
Demo
只是來輔助讀者更好的理解文章中的內容,應該博客結合Demo
一塊兒學習,只看Demo
仍是不能理解更深層的原理。Demo
中幾乎每一行代碼都會有註釋,各位能夠打斷點跟着Demo
執行流程走一遍,看看各個階段變量的值。
Demo地址:劉小壯的Github
這兩天更新了一下文章,將CoreData
系列的六篇文章整合在一塊兒,作了一個PDF
版的《CoreData Book》,放在我Github上了。PDF
上有文章目錄,方便閱讀。
若是你以爲不錯,請把PDF幫忙轉到其餘羣裏,或者你的朋友,讓更多的人瞭解CoreData,衷心感謝!