说明:按照《Core Data 应用开发》的思路整理记录
(一) 创建 CoreDataHelper
|-------------------------------| |------------------| |--------------------------------|
| 持久化存储协调器 | |托管对象模型| | 托管对象context |
|-------------------------------| |------------------| |--------------------------------|
| 持久化存储区 | | 对象图 | | |
| 数据表中的某行 <=======================> 托管对象 |
|__________________| |___________| |___________________|
1 持久化存储协调器 persistent store coordinator
NSPersistentStore : 用于创建持久化存储区
NSPersistentStoreCoordinator : 用于创建持久化存储协调器
2 托管对象模型(对象图)
NSManagedObjectModel : 用于创建托管对象模型
3 托管对象上下文
NSManagedObjectContext : 创建托管对象上下文
CoreDataHelper.h
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
@interface CoreDataHelper : NSObject
@property(nonatomic,readonly) NSManagedObjectContext *context; //上下文
@property(nonatomic,readonly) NSManagedObjectModel *model; //托管对象模型
@property(nonatomic,readonly) NSPersistentStoreCoordinator *coordinator; //持久化存储协调器
@property(nonatomic,readonly) NSPersistentStore *store; //持久化存储区
- (void)setupCoreData; //设置
- (void)saveContext; //将 _context 中的改变保存在 _store 中
@end
CoreDataHelper.m
#import "CoreDataHelper.h"
@implementation CoreDataHelper
//调试输出
#define debug 1
#pragma mark - FILES
//持久化真实存储文件名
NSString *storeFilename = @"Grocery-Dude.sqlite";
#pragma mark - PATHS
//获取沙盒 Documents 的路径
- (NSString *)applicationDocumentsDirectory{
if(debug == 1){
NSLog(@"Running %@ '%@'", self.class,NSStringFromSelector(_cmd));
}
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}
//创建 Documents 下文件夹 Stores
- (NSURL *)applicationStoresDirectory{
if(debug == 1){
NSLog(@"Running %@ '%@'", self.class,NSStringFromSelector(_cmd));
}
NSURL *storesDirectory = [[NSURL fileURLWithPath:[self applicationDocumentsDirectory]] URLByAppendingPathComponent:@"Stores"];
NSFileManager *filemanager = [NSFileManager defaultManager];
if(![filemanager fileExistsAtPath:[storesDirectory path]]){
NSError *error = nil;
if([filemanager createDirectoryAtURL:storesDirectory withIntermediateDirectories:YES attributes:nil error:&error]){
if(debug == 1){
NSLog(@"Successfully created Stores directory");
}
}else{
NSLog(@"Failed to create Stores directory: %@",error);
}
}
return storesDirectory;
}
//给 url 拼接最后的文件名 Grocery-Dude.sqlite
- (NSURL *)storeURL{
if(debug == 1){
NSLog(@"Running %@ '%@'", self.class,NSStringFromSelector(_cmd));
}
return [[self applicationStoresDirectory] URLByAppendingPathComponent:storeFilename];
}
#pragma mark - SETUP
- (id)init{
if(debug == 1){
NSLog(@"Running %@ '%@'", self.class,NSStringFromSelector(_cmd));
}
self = [super init];
if(!self){
return nil;
}
//根据对象图创建对象模型
_model = [NSManagedObjectModel mergedModelFromBundles:nil];
//根据对象模型创建持久化协调器
_coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:_model];
//创建某type型的上下文
_context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
//上下文和协调器连接
[_context setPersistentStoreCoordinator:_coordinator];
return self;
}
//加载sqlite持久化文件
- (void)loadStore{
if(debug == 1){
NSLog(@"Running %@ '%@'", self.class,NSStringFromSelector(_cmd));
}
if(_store){return;}
NSError *error = nil;
_store = [_coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[self storeURL] options:nil error:&error];
}
- (void)setupCoreData{
if(debug == 1){
NSLog(@"Running %@ '%@'", self.class,NSStringFromSelector(_cmd));
}
[self loadStore];
}
#pragma mark - SAVING
//将 _context 中的改变保存在 _store 中
- (void)saveContext{
if(debug == 1){
NSLog(@"Running %@ '%@'", self.class,NSStringFromSelector(_cmd));
}
if([_context hasChanges]){
NSError *error = nil;
if([_context save:&error]){
NSLog(@"_context SAVED changes to persistent store");
}else{
NSLog(@"Failed to save _context: %@", error);
}
}else{
NSLog(@"SKIPPED _context save, there are no changes!");
}
}
@end
(二) 创建托管对象模型 Data Model
(三) 生成 NSManagedObject
1.手动生成
对应的对象图:
对应的Code:
TestCD.h
#import <CoreData/CoreData.h>
@interface TestCD : NSManagedObject
@property(nonatomic,copy) NSString *name;
@end
TestCD.m
#import "TestCD.h"
@implementation TestCD
@dynamic name;
@end
这里用了 dynamic 关键字,因为 Core Data 在运行的时候会自动生成属性的存取方法
当属性多时,我们可以用nonnull和nullable等修饰属性,让属性是否可以为空
我们还可以加个类方法:+ (NSFetchRequest *)fetchRequest {
return [[NSFetchRequest alloc] initWithEntityName:@"Test"];
}
(四) 存储
NSArray *arrayObjs = @[@"Milk", @"Apples", @"Bread", @"Cheese", @"Orange Juice"];
for(NSString *name in arrayObjs){
TestCD *test = [NSEntityDescription insertNewObjectForEntityForName:@"Test" inManagedObjectContext:_coreDataHelper.context];
test.name = name;
}
[_coreDataHelper saveContext];
(五) 排序获取
// NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Test"];
NSFetchRequest *request = [TestCD fetchRequest];
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sort]];
NSArray *fetchedObjects = [_coreDataHelper.context executeFetchRequest:request error:nil];
for(TestCD *item in fetchedObjects){
NSLog(@"Fetched Object = %@", item.name);
}
(六) 筛选/删除
筛选用到谓词 NSPredicate
NSPredicate *filter = [NSPredicate predicateWithFormat:@"name = %@", @"Milk"];
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Test"];
[request setPredicate:filter];
NSArray *fetchedObjects = [_coreDataHelper.context executeFetchRequest:request error:nil];
for(TestCD *test in fetchedObjects){
NSLog(@"Fetched Object = %@", test.name);
}
获取请求模板:
在对象图上使用 FETCH REQUESTS
删除托管对象:
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Test"];
NSArray *fetchedObjects = [_coreDataHelper.context executeFetchRequest:request error:nil];
for(TestCD *test in fetchedObjects){
NSLog(@"Fetched Object = %@", test.name);
[_coreDataHelper.context deleteObject:test];
}
[_coreDataHelper saveContext];