引言:
Core Data 是 iOS 3.0 以後引入的資料持久化解決方案,其原理是對SQLite的封裝,是開發者不需要接觸SQL語句,就可以對資料庫進行的操作.
其編碼方式和原理結構方面較為特殊,本博文主要介紹在使用Core Data時遇到的各種問題以及對其核心原理進行解釋.
參考資料:
1: iOS教程:Core Data資料持久性存儲基礎教程
<a href="http://www.dasheyin.com/ios_jiao_cheng_core_data_shu_ju_chi_jiu_xing_cun_chu_ji_chu_jiao_cheng.html" target="_blank">http://www.dasheyin.com/ios_jiao_cheng_core_data_shu_ju_chi_jiu_xing_cun_chu_ji_chu_jiao_cheng.html</a>
安裝:
安裝的方式隻有一步,引入CoreData.framework 即可.
使用:
使用Core Data起步最先要了解和熟悉的類是以下三個:
1:NSManagedObjectModel
2:NSPersistentStoreCoordinator
3:NSManagedObjectContext
在此也特别的說明一下,如果你沒有了解透這三個類分别是做什麼的,那麼往後看到的代碼都有一種非常迷茫的感覺:
接下來分别介紹每一個類的具體功能和用途:
1.NSManagedObjectModel(管理對象模型,以下簡稱:上下文):
建構整個資料庫的表結構,表字段類型,表與表之間的關系(Relationship)等等凡是和資料結構有關的定義都通過此類來管理.
那麼使用此類需要一個Data Model(資料模型)檔案來配合其一起使用,如下圖所示建立出來:
那麼我們所有資料結構的定義和設計都用這個Data Model來完成.
在代碼方面需要通過檔案路徑的方式找到它,并初始化NSManagedObjectModel
注:建立Data Model檔案以後的檔案擴充名稱是: Data Model Name.xcdatamodeld但通過XCode編譯打包成App以後,其會被轉換成一個Data
Model Name.momd檔案.而我們真正要加的模型檔案就是這個Data Model Name.momd檔案.
2.NSPersistentStoreCoordinator(持久性資料協調器):
NSPersistentStoreCoordinator是真正意義上和SQLite打交道的類,主要根據NSManagedObjectModel 執行表結構的建立,通過NSManagedObjectContext 的指令執行資料互動
.
注:通過NSManagedObjectModel初始化,一旦初始化成功,SQLite的DB,就已經有了完善的表結構關系,不過這不是我們關心的重點,繼續往下.
3.NSManagedObjectContext(管理對象上下文)
NSManagedObjectContext是我們在開發中主要互動的類,資料的增删改查都通過上下文去觸發指令并傳回結果. 根據一個NSPersistentStoreCoordinator 完成初始化
到此,CoreData的準備工作已經完成,其實XCode已經有模版可以直接完成CoreData的準備工作,不過對于新手來說,最好還是一步一步來,加以了解,以便出現BUG時,能夠及時找到解決方案,貴在了解!
接下來,開始操縱資料!
插入一條?更新一條?删除一條?
熟悉Sql語句的同學:腦子裡立刻會想到:insert into table , update table , delete table
那麼在CoreData,這三項工作全部通過save函數來完成,一個函數完成三件事,CoreData這麼犀利的?
NSPredicate(條件擴充卡)
NSPredicate主要為NSFetchRequest而服務,提供查詢時的各種條件語句,方面過濾出複合業務需求的資料.
以下先列出 NSPredicate 支援的通配符
1:相等(==) 舉例: field == 'value'
2:不相等(!=) 舉例: field != 'value'
3:模糊(like) 舉例: field like '*value*' 或者 field like '?value?' like 使用?表示一個字元,*表示多個字元
4:比較( > < <= >= ) 舉例: field > 6
以上4種通配符都是字元串直接拼接即可,接下來的通配符在拼接字元串方面較為麻煩,但有相關代碼可以輔助拼接.
5:範圍(between) 舉例: field between {"6", "10"}
可以通過如下代碼拼接條件指令:
6:包含(in) 舉例: filed IN {"value1", "value2"}
7:複合(or and not) 舉例: filed == "value2" OR filed == "value3"
也可以通過如下代碼拼接:
在調用save 函數時我需要注意些什麼?
一個對象隻屬于一個上下文對象,是以不同上下文管轄的對象不允許用一個上下文來調用save 方法,這隻會失敗,錯誤提示如下:
Illegal attempt to establish a relationship 'xyz' between objects in different contexts
Persistent Store Coordinator (持久性資料協調器): 你可以将這個東西看作是資料庫連接配接庫,在這裡,你将設定資料存儲的名字和位置,以及資料存儲的時機。
Managed Object Context (管理資料内容):你可以将這一部分看作是資料的實際内容,這也是整個資料庫中對我們而言最重要的部分(這還用說),基本上,插入資料,查詢資料,删除資料的工作都在這裡完成。
NSFetchRequest* request = [[NSFetchRequest alloc] init];
[request setEntity:entity];[request setResultType:NSManagedObjectIDResultType];
[request setFetchBatchSize:20];
NSError* error = nil;
NSArray* items = [context executeFetchRequest:request error:&error];
for (NSManagedObjectID* objectID in items) {
NSManagedObject* object = [context objectWithID:objectID];
...}
countForFetchRequest:error
1:表與表之間關系建立教程
<a href="http://blog.csdn.net/fengsh998/article/details/8123392">http://blog.csdn.net/fengsh998/article/details/8123392</a>
2:針對應用更新和表結構變動時 相容舊版本的CoreData資料庫解決辦法.
遇到的問題:
當你将CoreData 加入到工程中,并啟動了App一切都運作良好,
可是開發途中修改了CoreData 的 資料結構,比如添加或者删除了某個字段,或者新添加了一張表.
此時,再運作App時,發現App直接Crash.
如何解決:
這說明CoreData無法做到時時的去修改表結構,但CoreData可以以多個副本的形式來處理資料結構變化時的Crash問題.
闡述一下原理: 原理類似SVN 需要打一個 tag 一樣, 一擔打了Tag 就意味着這個版本的代碼将不再允許修改,如果需要修改,需要到新的分枝裡去實作.
當利用開發工具建立CoreData 管理檔案以後:FEMicroCoopModel.xcdatamodeld 預設是隻有一個分枝的.
那麼添加分枝方式如下:
1.IDE->Editor->Add Model Version...
2.之後顯示如下界面:
兩個字段:
Version name:版本名稱(按你所需來取)
Based on model:基礎模型(這裡選擇一個,已經有的分枝,繼承的概念)
Finish之後就完成了,那麼新的資料結構修改,都請在這個檔案上面進行操作.
當你修改的差不多以後,需要設定 CoreData管理檔案的 (Versioned Core Data Model) 目前使用版本,如下圖:
隻有這樣應用運作時才會按照新版資料結構去遷移資料和修改表結構.
代碼方面隻有兩個地方需要注意一下:
1:添加對資料結構版本自适應的配置,代碼如下:
2:在執行個體化 NSManagedObjectModel 對象 需要傳入模型名稱,這裡隻要是你當初建立 CoreData管理對象時的名稱即可.
3:讓控制台擁有輸出 Core Data執行的SQL語句的能力.
為Edit Scheme - Run - Arguments - 添加一項值:
如下圖所示:
3:警告和錯誤
1:has no children
警告提示如下圖:
解決方法:
将圖中的勾勾去掉 編譯即可
總結: