一. CoreData 是什么?
- Core Data 是 iOS SDK 里的一個很強大的框架,允許程序員以面向對象的方式儲存和管理數據。使用 Core Data 框架,程序員可以很輕松有效地通過面向對象的接口管理數據
- Core Data 是一個模型層的技術。幫助建立代表程序狀態的模型層,Core Data 也是一種 持久化技術,能將模型對象的狀態持久化到磁盤,但它最重要的特點是: ** Core Data 不僅是一個加載、保存數據的框架,它還能和內存中的數據很好的共事**
- 在數據操作過程中, 無需編寫任何SQL語句
- Core Data 使用包括實體和實體間關系,以及查找符合某些條件實體的請求等內容
- 開發者可以在純對象層上查找與管理這些數據,而不必擔心存儲和查找的實現細節
- Core Data 框架最早出現在 Mac OS X 10.4 Tiger 與 iOS 3.0 系統,經過成千上萬的應用程序以及數以百萬用戶的反復的驗證,Core Data 確實已經是一套非常成熟的框架
- CoreData利用了Objective-C語言和運行時,巧妙地集成了CoreFoundation框架。是 一個易于使用的框架,不僅可以優雅地管理對象圖,而且在內存管理方面表現異常優異
二. 怎么學習CoreData
- 第一眼看到 Core Data 令人生畏的復雜架構關系,很多人都會有無從下手的感覺.
- 可是, 一旦理解了架構圖中各個部件的組成及相互之間的關系,就能體會到 Core Data API 的簡潔和直觀了
- Core Data stack(堆棧):如果能夠理解 Core Data stack 中的各個成員所扮演的角色,那么再使用Core Data 就不會感覺到困難了
- 誤區:Core Data 不是一個數據庫,不要用數據庫的眼光去看待 Core Data
- Core Data 不是應用程序的數據庫,也不是將數據持久化保存到數據庫的 API。Core Data 是一個用于管理對象圖的框架。Core Data 可以把對象圖寫入磁盤從而持久化保存,但是這不是框架的主要目標.
三. Core Data stack
Core Data stack 是 Core Data 的核心,由一組 Core Data 核心對象組成
- NSManagedObjectContext 對象管理上下文: 負責管理模型的對象的集合
- NSManagedObjectModel 被管理的對象模型: 負責管理對象模型
- NSPersistentStoreCoordinator 存儲調度器: 負責將數據保存到磁盤的
三者之間關系示意圖:
關系圖
分為兩部分:
- 對象圖管理
- 數據持久化
在這兩部分的中間,即堆棧中間,是持久化存儲協調器(Persistent Store Coordinator, PSC)。通過它將對象圖管理部分和持久化部分綁在一起。當這兩部分中的一部分需要和另一部分交互,將通過 PSC 來調節
對象圖
常見的使用解決方案:
解決方案
四. 創建CoreDataStack
根據 CoreDataStack 示意圖,將關系以代碼的形式組織起來 !
// 實例化數據模型
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:modelNamewithExtension:@"momd"];
NSManagedObjectModel *model = [[NSManagedObjectModel alloc]initWithContentsOfURL:modelURL];
// 實例化持久化儲存
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
NSURL *dbURL = [[[NSFileManager defaultManager]URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]lastObject];
dbURL = [dbURL URLByAppendingPathComponent:dbName];[psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil
URL:dbURL options:nil error:NULL];
// 實例化上下文
_managedObjectContext = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSMainQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator:psc];
[ 一些提示 ]
use scalar properties for primitive data type
在 iOS5 和 OS X10.7 之前,scalar 不能自動生成,程序員必須自己添加 setter 和 getter 的實現
@dynamic
在 Objective-C 中,如果將某個屬性實現為@dynamic,意味著告訴編譯器不會在編譯時確定這個屬性的行為實現,因此不需要在編譯期間對這個屬性的 getter、setter 做檢查.
五. CoreData 常見操作
5.1 新增記錄:
使用 NSEntityDescription 來創建對象,賦值后使用相應的 context 保存即可
新增
5.2 刪除記錄:
使用 context 的 deleteObject:刪除被管理的模型對象后保存即可
刪除記錄
5.3 修改記錄:
直接修改模型對象保存即可
修改記錄
5.4 查詢記錄
對使用 CoreData 進行存儲的數據進行一定條件的查詢后取出來使用
5.4.1 謂詞(is)---NSPredicate
作用:判斷條件表達式的求值返回真或假的過程
使用步驟:
- 定義 NSPredicate 對象并指定條件
- 調用謂詞的 evaluateWithObject 方法判斷指定條件是否滿足示例:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"self CONTAINS '1'"];
NSString *text = @"1234";
NSLog(@"%d", [predicate evaluateWithObject:text]);
案例:
- 創建 Person 的對象數組
- 查詢判斷姓名和年齡的過濾方法
- 傳統方法
NSMutableArray *result = [NSMutableArray arrayWithCapacity:personList.count];
for (NSInteger i = 0; i < personList.count; i++)
{
Person *person = personList[i];
// 用戶年齡小于5同時用戶姓名中包含"1"字符串
if (person.age < 5 && NSNotFound != [person.name rangeOfString:@"1"].location)
{
[result addObject:person];
}
}
return result;
- 謂詞方法
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name CONTAINS '1' && %K BETWEEN {%d, %d}",@"age", 5, 15];
NSArray *result = [personList filteredArrayUsingPredicate:predicate];
謂詞的條件指令
> < == >= <= !=
例如:
@"number >= 99"
范圍運算符
IN BETWEEN
例如:
@"number BETWEEN {1,5}"
@"address IN {'shanghai','nanjing'}"
字符串本身
:SELF
例如:
@"SELF == 'APPLE'"
字符串相關:
BEGINSWITH ENDSWITH CONTAINS
例如:
@"name CONTAIN[cd] 'ang'" //包含某個字符串
@"name BEGINSWITH[c] 'sh'" //以某個字符串開頭
@"name ENDSWITH[d] 'ang'" //以某個字符串結尾
- 通配符:
LIKE
例如:
@"name LIKE[cd] '*er*'" //* 代表通配符,Like 代表接受 [cd].
@"name LIKE[cd] '???er*'"
注: 星號"*" : 代表0或多個字符
問號"?" : 代表一個字符
- 正則表達式:MATCHES
例如:
NSString *regex = @"^A.+e$"; //以A開頭, e結尾
@"name MATCHES %@",regex
注:[c]不區分大小寫,[d]不區分發音符號即沒有重音符號,[cd]既不區分大小寫,也不區分發音符號.
- 合計操作
ANY SOME: 指定下列表達式中的任意元素
例如ANY children.age < 18
ALL: 指定下列表達式中的所有元素
例如ALL children.age < 18
NONE: 指定下列表達式中沒有的元素
例如NONE children.age < 18
在邏輯上等于NOT(ANY ...)
IN:等于 SQL的IN
操作,左邊的表達必須出現在與右邊指定的集合中
例如:name IN { 'Ben','Melissa', 'Nick' }
提示 :
- 謂詞中的匹配指令關鍵字通常使用大寫字母
- 謂詞中可以使用格式字符串
- 如果通過對象的
key path
指定匹配條件,需要使用 %K