最新CoreData封装Demo
1、创建CoreData文件
2、
3、
4、
UploadCoreDataAPI.h
// // UploadCoreDataAPI.h // dsafsda // // Created by 冯敏 on 17/3/2. // Copyright © 2017年 FengMin_Team. All rights reserved. // #import <Foundation/Foundation.h> #import "CoreDataAPI.h" #import "ResourceModel.h" #import "DownLoadModel.h" @interface UploadCoreDataAPI : NSObject /** * 上传数据库模型名称 */ @property (nonatomic,copy,readonly) NSString *coreDataModelName; /** * 上传数据库实体名称 */ @property (nonatomic,copy,readonly) NSString *coreDataEntityName; /** * 上传数据库存储路径 */ @property (nonatomic,copy,readonly) NSString *coreDataSqlPath; + (instancetype)sharedInstance; /** * 插入上传记录 * * @param model 数据模型 * @param success 成功回调 * @param fail 失败回调 */ - (void)insertUploadModel:(ResourceModel *)model success:(void(^)(void))success fail:(void(^)(NSError *error))fail; /** * 更新上传记录 * * @param model 数据模型 * @param success 成功回调 * @param fail 失败回调 */ - (void)updateUploadModel:(DownLoadModel *)model success:(void(^)(void))success fail:(void(^)(NSError *error))fail; /** * 删除一条上传记录 * * @param model 数据模型 * @param success 成功回调 * @param fail 失败回调 */ - (void)deleteUploadModel:(DownLoadModel *)model success:(void(^)(void))success fail:(void(^)(NSError *error))fail; /** * 删除所有上传记录 * * @param success 成功回调 * @param fail 失败回调 */ - (void)deleteAllUploadModel:(void(^)(void))success fail:(void(^)(NSError *error))fail; /** * 查询上传数据库所有数据 * * @param success 成功回调(finishArray:已完成(DownLoadModel对象数组) unfinishedArray:未完成(DownLoadModel对象数组)) * @param fail 失败回调 */ - (void)readAllUploadModel:(void(^)(NSArray *finishArray,NSArray *unfinishedArray))success fail:(void(^)(NSError *error))fail; @end
UploadCoreDataAPI.m
// // UploadCoreDataAPI.m // dsafsda // // Created by 冯敏 on 17/3/2. // Copyright © 2017年 FengMin_Team. All rights reserved. // #import "UploadCoreDataAPI.h" static NSString * const modelName = @"Upload"; static NSString * const entityName = @"UploadEntity"; static NSString * const sqliteName = @"Upload.sqlite"; @interface UploadCoreDataAPI () @property (nonatomic,strong) CoreDataAPI * uploadData; @end @implementation UploadCoreDataAPI static UploadCoreDataAPI * uploadCoreData = nil; + (instancetype)sharedInstance { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ uploadCoreData = [[UploadCoreDataAPI alloc] init]; }); return uploadCoreData; } + (instancetype)allocWithZone:(struct _NSZone *)zone { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ if (uploadCoreData == nil) { uploadCoreData = [super allocWithZone:zone]; } }); return uploadCoreData; } - (instancetype)init { if (self = [super init]) { [self initUploadCoreData]; } return self; } - (void)initUploadCoreData { _coreDataEntityName = entityName; _coreDataModelName = modelName; _coreDataSqlPath = [[self getDocumentPath] stringByAppendingPathComponent:sqliteName]; self.uploadData = [[CoreDataAPI alloc] initWithCoreData:self.coreDataEntityName modelName:self.coreDataModelName sqlPath:self.coreDataSqlPath success:^{ NSLog(@"initUploadCoreData success"); } fail:^(NSError *error) { NSLog(@"initUploadCoreData fail"); }]; } - (NSString *)getDocumentPath { NSString * path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; return path; } #pragma mark - -- 插入上传记录 - (void)insertUploadModel:(ResourceModel *)model success:(void(^)(void))success fail:(void(^)(NSError *error))fail { NSString * fileName = model.fileName; NSString * fileSize = [NSString stringWithFormat:@"%.2lf",model.size]; NSString * urlPath = model.path; NSNumber * time = [NSNumber numberWithInt:[[NSDate date] timeIntervalSince1970]]; NSNumber * fileType = model.fileType; NSNumber * finishStatus = [NSNumber numberWithBool:NO]; NSDictionary * dict = NSDictionaryOfVariableBindings(fileName,fileSize,urlPath,time,fileType,finishStatus); [self.uploadData insertNewEntity:dict success:^{ if (success) { success(); } } fail:^(NSError *error) { if (fail) { fail(error); } }]; } #pragma mark - -- 更新上传记录 - (void)updateUploadModel:(DownLoadModel *)model success:(void(^)(void))success fail:(void(^)(NSError *error))fail { // NSString * filterStr = [NSString stringWithFormat:@"time = %f AND urlPath = '%@' AND fileName = '%@'",model.time,model.urlPath,model.fileName]; // NSString * filterStr = [NSString stringWithFormat:@"fileName CONTAINS %@",model.fileName]; NSString * filterStr = [NSString stringWithFormat:@"fileName = %@",model.fileName]; [self.uploadData readEntity:nil ascending:YES filterStr:filterStr success:^(NSArray *results) { if (results.count > 0) { NSManagedObject * obj = [results firstObject]; // [obj setValue:[NSNumber numberWithBool:model.urlPath] forKey:@"urlPath"]; [obj setValue:model.urlPath forKey:@"urlPath"]; [self.uploadData updateEntity:^{ if (success) { success(); } } fail:^(NSError *error) { if (fail) { fail(error); } }]; } } fail:^(NSError *error) { if (fail) { fail(error); } }]; } #pragma mark - -- 删除一条上传记录 - (void)deleteUploadModel:(DownLoadModel *)model success:(void(^)(void))success fail:(void(^)(NSError *error))fail { // NSString * filterStr = [NSString stringWithFormat:@"time = %f AND urlPath = '%@' AND fileName = '%@'",model.time,model.urlPath,model.fileName]; NSString * filterStr = [NSString stringWithFormat:@"fileName = %@",model.fileName]; [self.uploadData readEntity:nil ascending:YES filterStr:filterStr success:^(NSArray *results) { if (results.count>0) { NSManagedObject *obj = [results firstObject]; [self.uploadData deleteEntity:obj success:^{ if (success) { success(); } } fail:^(NSError *error) { if (fail) { fail(error); } }]; } } fail:^(NSError *error) { if (fail) { fail(error); } }]; } #pragma mark - -- 删除所有上传记录 - (void)deleteAllUploadModel:(void(^)(void))success fail:(void(^)(NSError *error))fail { [self.uploadData readEntity:nil ascending:YES filterStr:nil success:^(NSArray *results) { for (NSManagedObject *obj in results){ [self.uploadData deleteEntity:obj success:^{ if (success) { success(); } } fail:^(NSError *error) { if (fail) { fail(error); } }]; } } fail:^(NSError *error) { if (fail) { fail(error); } }]; } #pragma mark - -- 查询所有上传记录 - (void)readAllUploadModel:(void(^)(NSArray *finishArray,NSArray *unfinishedArray))success fail:(void(^)(NSError *error))fail { [self.uploadData readEntity:nil ascending:YES filterStr:nil success:^(NSArray *results) { NSMutableArray * finishArray = [NSMutableArray array]; NSMutableArray * unfinishedArray = [NSMutableArray array]; for (NSManagedObject *obj in results) { DownLoadModel * model = [[DownLoadModel alloc] init]; // 获取数据库中各个键值的值 model.fileName = [obj valueForKey:@"fileName"]; model.fileSize = [obj valueForKey:@"fileSize"]; model.urlPath = [obj valueForKey:@"urlPath"]; model.time = [[obj valueForKey:@"time"] intValue]; model.fileType = [[obj valueForKey:@"fileType"] intValue]; model.imageData = [obj valueForKey:@"imageData"]; model.finishStatus = [[obj valueForKey:@"finishStatus"] intValue]; if (model.finishStatus) { [finishArray addObject:model]; } else { [unfinishedArray addObject:model]; } } if (success) { success(finishArray,unfinishedArray); } } fail:^(NSError *error) { if (fail) { fail(error); } }]; } @end
5、
CoreDataAPI.h
// // CoreDataAPI.h // dsafsda // // Created by 冯敏 on 17/3/2. // Copyright © 2017年 FengMin_Team. All rights reserved. // #import <Foundation/Foundation.h> #import <CoreData/CoreData.h> @interface CoreDataAPI : NSObject /** * 获取数据库存储的路径 */ @property (nonatomic,copy,readonly) NSString *sqlPath; /** * 获取.xcdatamodeld文件的名称 */ @property (nonatomic,copy,readonly) NSString *modelName; /** * 获取.xcdatamodeld文件中创建的实体的名称 */ @property (nonatomic,copy,readonly) NSString *entityName; /** * 创建CoreData数据库 * * @param entityName 实体名称 * @param modelName .xcdatamodeld文件名称(为nil则主动从程序包加载模型文件) * @param sqlPath 数据库存储的路径 * @param success 成功回调 * @param fail 失败回调 * * @return 返回CoreDataAPI对象 */ - (instancetype)initWithCoreData:(NSString *)entityName modelName:(NSString *)modelName sqlPath:(NSString *)sqlPath success:(void(^)(void))success fail:(void(^)(NSError *error))fail; /** * 插入数据 * * @param dict 字典中的键值对必须要与实体中的每个名字一一对应 * @param success 成功回调 * @param fail 失败回调 */ - (void)insertNewEntity:(NSDictionary *)dict success:(void(^)(void))success fail:(void(^)(NSError *error))fail; /** * 查询数据 * * @param sequenceKeys 数组高级排序(数组里存放实体中的key,顺序按自己需要的先后存放即可),实体key来排序 * @param isAscending 是否上升排序 * @param filterStr 过滤语句 * @param success 成功后结果回调 * @param fail 失败回调 */ - (void)readEntity:(NSArray *)sequenceKeys ascending:(BOOL)isAscending filterStr:(NSString *)filterStr success:(void(^)(NSArray *results))success fail:(void(^)(NSError *error))fail; /** * 删除数据 * * @param entity NSManagedObject * @param success 成功回调 * @param fail 失败回调 */ - (void)deleteEntity:(NSManagedObject *)entity success:(void(^)(void))success fail:(void(^)(NSError *error))fail; /** * 更新数据 * * @param success 成功回调 * @param fail 失败回调 */ - (void)updateEntity:(void(^)(void))success fail:(void(^)(NSError *error))fail; @end
CoreDataAPI.m
// // CoreDataAPI.m // dsafsda // // Created by 冯敏 on 17/3/2. // Copyright © 2017年 FengMin_Team. All rights reserved. // /** * 知识点: NSManagedObject: 通过Core Data从数据库中取出的对象,默认情况下都是NSManagedObject对象. NSManagedObject的工作模式有点类似于NSDictionary对象,通过键-值对来存取所有的实体属性. setValue:forkey:存储属性值(属性名为key); valueForKey:获取属性值(属性名为key). 每个NSManagedObject都知道自己属于哪个NSManagedObjectContext NSManagedObjectContext: 负责数据和应用库之间的交互(CRUD,即增删改查、保存等接口都在这个对象中). 所有的NSManagedObject都存在于NSManagedObjectContext中,所以对象和context是相关联的 每个 context 和其他 context 都是完全独立的 每个NSManagedObjectContext都知道自己管理着哪些NSManagedObject NSPersistentStoreCoordinator: 添加持久化存储库,CoreData的存储类型(比如SQLite数据库就是其中一种) 中间审查者,用来将对象图管理部分和持久化部分捆绑在一起,负责相互之间的交流(中介一样) NSManagedObjectModel: Core Data的模型文件 NSEntityDescription: 用来描述实体:相当于数据库表中一组数据描述 */ #import "CoreDataAPI.h" @interface CoreDataAPI () /** * 数据模型对象 */ @property (nonatomic,strong) NSManagedObjectModel * model; /** * 上下文 */ @property (nonatomic,strong) NSManagedObjectContext * context; /** * 持久性存储区 */ @property (nonatomic,strong) NSPersistentStoreCoordinator * persistent; @end @implementation CoreDataAPI - (instancetype)initWithCoreData:(NSString *)entityName modelName:(NSString *)modelName sqlPath:(NSString *)sqlPath success:(void(^)(void))success fail:(void(^)(NSError *error))fail { if (self = [super init]) { // 断言(实体名称和存储路径是否为nil) // ... _entityName = entityName; _modelName = modelName; _sqlPath = sqlPath; // 初始化上下文 self.context = [[NSManagedObjectContext alloc] init]; if (modelName) { //获取模型路径 NSURL * modelURL = [[NSBundle mainBundle] URLForResource:modelName withExtension:@"momd"];//xcdatamodeld //根据模型文件创建模型对象 self.model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; } else { // 从应用程序包中加载模型文件 self.model = [NSManagedObjectModel mergedModelFromBundles:nil]; } // 以传入模型方式初始化持久化存储库 self.persistent = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.model]; /* 持久化存储库的类型: NSSQLiteStoreType SQLite数据库 NSBinaryStoreType 二进制平面文件 NSInMemoryStoreType 内存库,无法永久保存数据 虽然这3种类型的性能从速度上来说都差不多,但从数据模型中保留下来的信息却不一样 在几乎所有的情景中,都应该采用默认设置,使用SQLite作为持久化存储库 */ // 添加一个持久化存储库并设置类型和路径,NSSQLiteStoreType:SQLite作为存储库 NSError * error = nil; [self.persistent addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:sqlPath] options:nil error:&error]; if (error) { NSLog(@"添加数据库失败:%@",error); if (fail) { fail(error); } } else { NSLog(@"添加数据库成功"); // 设置上下文所要关联的持久化存储库 self.context.persistentStoreCoordinator = self.persistent; if (success) { success(); } } } return self; } // 添加数据 - (void)insertNewEntity:(NSDictionary *)dict success:(void(^)(void))success fail:(void(^)(NSError *error))fail { if (!dict||dict.allKeys.count == 0) return; // 通过传入上下文和实体名称,创建一个名称对应的实体对象(相当于数据库一组数据,其中含有多个字段) NSManagedObject * newEntity = [NSEntityDescription insertNewObjectForEntityForName:self.entityName inManagedObjectContext:self.context]; // 实体对象存储属性值(相当于数据库中将一个值存入对应字段) for (NSString *key in [dict allKeys]) { [newEntity setValue:[dict objectForKey:key] forKey:key]; } // 保存信息,同步数据 NSError *error = nil; BOOL result = [self.context save:&error]; if (!result) { NSLog(@"添加数据失败:%@",error); if (fail) { fail(error); } } else { NSLog(@"添加数据成功"); if (success) { success(); } } } // 查询数据 - (void)readEntity:(NSArray *)sequenceKeys ascending:(BOOL)isAscending filterStr:(NSString *)filterStr success:(void(^)(NSArray *results))success fail:(void(^)(NSError *error))fail { // 1.初始化一个查询请求 NSFetchRequest * request = [[NSFetchRequest alloc] init]; // 2.设置要查询的实体 NSEntityDescription * desc = [NSEntityDescription entityForName:self.entityName inManagedObjectContext:self.context]; request.entity = desc; // 3.设置查询结果排序 if (sequenceKeys && sequenceKeys.count > 0) { // 如果进行了设置排序 NSMutableArray * array = [NSMutableArray array]; for (NSString * key in sequenceKeys) { /** * 设置查询结果排序 * sequenceKey:根据某个属性(相当于数据库某个字段)来排序 * isAscending:是否升序 */ NSSortDescriptor * sort = [NSSortDescriptor sortDescriptorWithKey:key ascending:isAscending]; [array addObject:sort]; } if (array.count > 0) { request.sortDescriptors = array;// 可以添加多个排序描述器,然后按顺序放进数组即可 } } // 4.设置条件过滤 if (filterStr) { // 如果设置了过滤语句 //time = 1488522112.000000 AND urlPath = 'path' AND fileName = '111' NSPredicate * predicate = [NSPredicate predicateWithFormat:filterStr]; request.predicate = predicate; } // 5.执行请求 NSError * error = nil; NSArray * objs = [self.context executeFetchRequest:request error:&error]; // 获得查询数据数据集合 if (error) { if (fail) { fail(error); } } else{ if (success) { success(objs); } } } // 更新数据 - (void)updateEntity:(void(^)(void))success fail:(void(^)(NSError *error))fail { NSError * error = nil; [self.context save:&error]; if (error) { NSLog(@"删除失败:%@",error); if (fail) { fail(error); } } else { if (success) { success(); } } } // 删除数据 - (void)deleteEntity:(NSManagedObject *)entity success:(void(^)(void))success fail:(void(^)(NSError *error))fail { // 传入需要删除的实体对象 [self.context deleteObject:entity]; // 同步到数据库 NSError *error = nil; [self.context save:&error]; if (error) { NSLog(@"删除失败:%@",error); if (fail) { fail(error); } } else { if (success) { success(); } } } @end
6、
ResourceModel.h
#import <Foundation/Foundation.h> #import <UIKit/UIKit.h> @interface ResourceModel : NSObject @property (nonatomic, copy) NSString * fileName; @property (nonatomic, assign) CGFloat size; @property (nonatomic, copy) NSString * path; @property (nonatomic, assign) NSNumber * fileType; //@property (nonatomic, retain) NSData * imageData; //@property (nonatomic, assign) NSNumber * finishStatus; //@property (nonatomic, assign) NSNumber * time; @end
DownLoadModel.h
#import <Foundation/Foundation.h> @interface DownLoadModel : NSObject @property (nonatomic, assign) float time; @property (nonatomic, copy) NSString * urlPath; @property (nonatomic, copy) NSString * fileName; @property (nonatomic, assign) NSInteger finishStatus; @property (nonatomic, copy) NSString * fileSize; @property (nonatomic, assign) NSInteger fileType; @property (nonatomic, strong) NSData * imageData; @end
7、
ViewController.m
ResourceModel * resourceModel = [[ResourceModel alloc] init]; resourceModel.fileName = @"666"; resourceModel.size = 2.222; resourceModel.path = @"path111"; resourceModel.fileType = @2; // [[UploadCoreDataAPI sharedInstance] insertUploadModel:resourceModel success:^{ // NSLog(@"insertSucess"); // } fail:^(NSError *error) { // NSLog(@"insertError"); // }]; DownLoadModel * downloadModel = [[DownLoadModel alloc] init]; downloadModel.fileName = @"111"; downloadModel.time = 1488522049; downloadModel.urlPath = @"jklsdfaljfalsdkfjlsd"; // [[UploadCoreDataAPI sharedInstance] updateUploadModel:downloadModel success:^{ // NSLog(@"updateSucess"); // } fail:^(NSError *error) { // NSLog(@"updateError"); // }]; // [[UploadCoreDataAPI sharedInstance] deleteUploadModel:downloadModel success:^{ // NSLog(@"deleteSucess"); // } fail:^(NSError *error) { // NSLog(@"deleteError"); // }]; // [[UploadCoreDataAPI sharedInstance] deleteAllUploadModel:^{ // NSLog(@"deleteSucess"); // } fail:^(NSError *error) { // NSLog(@"deleteError"); // }]; [[UploadCoreDataAPI sharedInstance] readAllUploadModel:^(NSArray *finishArray, NSArray *unfinishedArray) { NSLog(@"finishArray: %@",finishArray); NSLog(@"unfinishedArray: %@",unfinishedArray); for (DownLoadModel * downloadModel in unfinishedArray) { NSLog(@"fileName = %@\n urlPath = %@",downloadModel.fileName,downloadModel.urlPath); } } fail:^(NSError *error) { NSLog(@"readError"); }];