CoreData 從入門到精通 (一) 數(shù)據(jù)模型 + CoreData 棧的創(chuàng)建
概述
CoreData 是 Cocoa 平臺(tái)上用來管理模型層數(shù)據(jù)和數(shù)據(jù)持久化的一個(gè)框架歇僧,說簡(jiǎn)單點(diǎn)擂达,就是一個(gè)數(shù)據(jù)庫(kù)存儲(chǔ)框架番刊。CoreData 里相關(guān)的概念比較多忙芒,而且初始化也非常繁瑣,所以對(duì)初學(xué)者的學(xué)習(xí)還是有一些困難的。這篇文章將從頭到尾詳細(xì)地講一遍 CoreData 的使用方法,從 CoreData 的初始化到簡(jiǎn)單的增刪改查奄薇,再到批量處理,數(shù)據(jù)模型的版本更新以及和 TableView 的結(jié)合等抗愁,真正讓你能徹底了解 CoreData馁蒂。
一、CoreData 數(shù)據(jù)模型的創(chuàng)建
想要使用 CoreData 蜘腌,第一部是是創(chuàng)建數(shù)據(jù)模型沫屡,它描述了數(shù)據(jù)的結(jié)構(gòu)和關(guān)聯(lián)關(guān)系等〈橹椋可以理解為數(shù)據(jù)庫(kù)中的表結(jié)構(gòu)沮脖。在 Xcode 創(chuàng)建工程時(shí),提供了創(chuàng)建 CoreData 的模板,只需要我們?cè)趧?chuàng)建時(shí)勺届,勾選 CoreData 選項(xiàng)驶俊,Xcode 就會(huì)自動(dòng)創(chuàng)建出數(shù)據(jù)模型文件:
它是一個(gè) .xcdatamodeld 格式的文件:
如果創(chuàng)建時(shí)沒有勾選 CoreData,當(dāng)然也可以在 File -> new -> file 里手動(dòng)添加這個(gè)文件:
然后打開這個(gè)文件涮因,是這樣的:
點(diǎn)擊下面的 Add Entity 按鈕可以添加一個(gè)Entity废睦,也就是一個(gè)數(shù)據(jù)實(shí)體,相當(dāng)于數(shù)據(jù)庫(kù)中的一張表:
點(diǎn)擊添加一個(gè) Student 的 Entity:
圖中的 Attributes 是定義屬性的地方养泡,Relationships 是定義關(guān)聯(lián)關(guān)系的地方嗜湃,點(diǎn)擊加號(hào)可以添加。下面來給 Student 添加三個(gè)字段:studentName, studentAge, studentId:
下面是 CoreData 里支持的數(shù)據(jù)類型:
選中一個(gè)字段澜掩,可以在右側(cè)的面板中對(duì)它做一些自定義:
例如在 validation 里對(duì)數(shù)據(jù)做一些限制购披,字符串的長(zhǎng)度,數(shù)字類型的最大最下值肩榕;設(shè)置索引刚陡、默認(rèn)值等。不同的數(shù)據(jù)類型可以設(shè)置不同的內(nèi)容株汉,一般維持默認(rèn)就可以筐乳。
另外對(duì)于每一個(gè) entity 實(shí)體類,Build 過后 Xcode 都會(huì)自動(dòng)幫我們生成相應(yīng)的實(shí)體類代碼乔妈,生成的代碼不會(huì)在工程目錄中顯示出來蝙云,但是可以通過導(dǎo)入頭文件索引到;當(dāng)然也可以配置成手動(dòng)生成的路召,選中對(duì)應(yīng)的 Entity 然后點(diǎn)擊右側(cè)面板的 Codegen勃刨,把 ClassDefinition 修改成 Manual/None,然后 Xcode 就不會(huì)再自動(dòng)生成了股淡。
另外身隐,Xcode 自動(dòng)生成的代碼都是 Swift 語(yǔ)言的,如果想改成Objc唯灵,可以在這里改:
這個(gè)時(shí)候也可以通過 Editor -> Create NSManagedObject Subclass 來生成相應(yīng)的實(shí)體類:
需要注意的是贾铝,如果前面有自動(dòng)生成過這些類文件,手動(dòng)生成后可能會(huì)編譯出錯(cuò)埠帕,因?yàn)楣こ汤飼?huì)索引到兩份同樣的代碼忌傻,這個(gè)時(shí)候需要 Clean 一下工程再 Build 即可。
下面是自動(dòng)生成的實(shí)體類:
到此為止搞监,CoreData 的數(shù)據(jù)模型就創(chuàng)建好了水孩。
二、CoreData 棧的創(chuàng)建
數(shù)據(jù)模型創(chuàng)建好之后琐驴,想要使用 CoreData 進(jìn)行數(shù)據(jù)持久化俘种,下一步就是初始化 CoreData 棧了秤标。下面是蘋果文檔里對(duì) CoreData 棧的介紹:
The Core Data stack is a collection of framework objects that are accessed as part of the initialization of Core Data and that mediate between the objects in your application and external data stores.
CoreData 棧是 CoreData 初始化被訪問的框架對(duì)象的集合,以及應(yīng)用中數(shù)據(jù)對(duì)象和外部數(shù)據(jù)存儲(chǔ)的媒介宙刘。CoreData 的初始化需要一步步地初始化 CoreData 棧上的三個(gè)對(duì)象結(jié)構(gòu)苍姜,它們分別是:
- NSManagedObjectModel — 描述了數(shù)據(jù)模型的結(jié)構(gòu)信息
- NSPersistentStoreCoordinator — 數(shù)據(jù)持久層和內(nèi)存對(duì)象模型的協(xié)調(diào)器
- NSManagedObjectContext — 內(nèi)存中 managedObject 對(duì)象的上下文
下圖是 CoreData 棧的結(jié)構(gòu),圖片來自 objc.io 的圖書 《CoreData》:
下面來用代碼演示 CoreData 棧的初始化過程:
1悬包、加載 ManagedObjectModel
第一步是創(chuàng)建 NSManagedObjectModel 對(duì)象衙猪,它需要通過上文中講的數(shù)據(jù)模型文件來創(chuàng)建:
@interface Appdelegate ()
@property (nonatomic, readwrite, strong) NSManagedObjectModel *managedObjectModel;
@end
@implementation
// 使用懶加載的方式初始化
- (NSManagedObjectModel *)managedObjectModel {
if (!_managedObjectModel) {
// url 為CoreDataDemo.xcdatamodeld,注意擴(kuò)展名為 momd布近,而不是 xcdatamodeld 類型
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"CoreDataDemo" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
}
return _managedObjectModel;
}
@end
2垫释、創(chuàng)建 PersistentStoreCoordinator
創(chuàng)建好 managedObjectModel
后就可以來創(chuàng)建 persistentStoreCoordinator
了,因?yàn)樗膭?chuàng)建需要用到 managedObjectModel
撑瞧,managedObjectModel
告訴了persistentStoreCoordinator
數(shù)據(jù)模型的結(jié)構(gòu)棵譬,然后 persistentStoreCoordinator
會(huì)根據(jù)對(duì)應(yīng)的模型結(jié)構(gòu)創(chuàng)建持久化的本地存儲(chǔ)。
@interface AppDelegate ()
@property (nonatomic, readwrite, strong) NSManagedObjectModel *managedObjectModel;
@property (nonatomic, readwrite, strong) NSPersistentStoreCoordinator *persistentStoreCoordinator;
@end
@implementation AppDelegate
- (NSManagedObjectModel *)managedObjectModel {
if (!_managedObjectModel) {
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"CoreDataDemo" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
}
return _managedObjectModel;
}
// 同樣使用懶加載創(chuàng)建
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (!_persistentStoreCoordinator) {
// 創(chuàng)建 coordinator 需要傳入 managedObjectModel
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel];
// 指定本地的 sqlite 數(shù)據(jù)庫(kù)文件
NSURL *sqliteURL = [[self documentDirectoryURL] URLByAppendingPathComponent:@"CoreDataDemo.sqlite"];
NSError *error;
// 為 persistentStoreCoordinator 指定本地存儲(chǔ)的類型预伺,這里指定的是 SQLite
[_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:sqliteURL
options:nil
error:&error];
if (error) {
NSLog(@"falied to create persistentStoreCoordinator %@", error.localizedDescription);
}
}
return _persistentStoreCoordinator;
}
// 用來獲取 document 目錄
- (nullable NSURL *)documentDirectoryURL {
return [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask].firstObject;
}
@end
3订咸、創(chuàng)建 ManagedObjectContext
上面兩步都完成之后,下面來創(chuàng)建 managedObjectContext
, 這也是平時(shí)操作 CoreData 主要會(huì)用到的對(duì)象:
@interface
...
@property (nonatomic, readwrite, strong) NSManagedObjectContext *context;
...
@end
@implementation
...
- (NSManagedObjectContext *)context {
if (!_context) {
// 指定 context 的并發(fā)類型: NSMainQueueConcurrencyType 或 NSPrivateQueueConcurrencyType
_context = [[NSManagedObjectContext alloc ] initWithConcurrencyType:NSMainQueueConcurrencyType];
_context.persistentStoreCoordinator = self.persistentStoreCoordinator;
}
return _context;
}
...
@end
至此酬诀,CoreData 棧的初始化就創(chuàng)建完成了脏嚷。以后操作 CoreData 就可以通過 context 屬性來完成,操作完之后調(diào)用 context
的 save
方法就可以數(shù)據(jù)持久化到本地瞒御。