<簡書 — 劉小壯> http://www.jianshu.com/p/61b7a615508cios
到目前爲止,已經將CoreData
相關的知識點都講完了。在這篇文章中,主要講一個
CoreData
第三方庫-MagicalRecord
。目前爲止這個第三方在Github
上有9500+的Star
,是全部CoreData
第三方庫中使用最多、功能最全的。在文章的後面還會對CoreData
作一個總結,以及對本系列全部文章作一個總結。git文章中若有疏漏或錯誤,還請各位及時提出,謝謝!😊github
CoreData
是蘋果自家推出的一個持久化框架,使用起來更加面向對象。可是在使用過程當中會出現大量代碼,並且CoreData
學習曲線比較陡峭,若是掌握很差,在使用過程當中很容易形成其餘問題。數據庫
國外開發者開源了一個基於CoreData
封裝的第三方——MagicalRecord
,就像是FMDB
封裝SQLite
同樣,MagicalRecord
封裝的CoreData
,使得原生的CoreData
更加容易使用。而且MagicalRecord
下降了CoreData
的使用門檻,不用去手動管理以前的PSC
、MOC
等對象。編程
根據Github
上MagicalRecord
的官方文檔,MagicalRecord
的優勢主要有三條:數據結構
1. 清理項目中CoreData
代碼
2. 支持清晰、簡單、一行式的查詢操做
3. 當須要優化請求時,能夠獲取NSFetchRequest
進行修改併發
將MagicalRecord
添加到項目中,和使用其餘第三方同樣,能夠經過下載源碼和CocoaPods
兩種方式添加。app
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
。
好多同窗都問我有Demo
沒有,其實文章中貼出的代碼組合起來就是個Demo
。後來想了想,仍是給本系列文章配了一個簡單的Demo
,方便你們運行調試,後續會給全部博客的文章都加上Demo
。
Demo
只是來輔助讀者更好的理解文章中的內容,應該博客結合Demo
一塊兒學習,只看Demo
仍是不能理解更深層的原理。Demo
中幾乎每一行代碼都會有註釋,各位能夠打斷點跟着Demo
執行流程走一遍,看看各個階段變量的值。
Demo地址:劉小壯的Github
這兩天更新了一下文章,將CoreData
系列的六篇文章整合在一塊兒,作了一個PDF
版的《CoreData Book》,放在我Github上了。PDF
上有文章目錄,方便閱讀。
若是你以爲不錯,請把PDF幫忙轉到其餘羣裏,或者你的朋友,讓更多的人瞭解CoreData,衷心感謝!😁