1、简介
CoreData是iOS5后,苹果提供的原生的用于对象化管理数据并且持久化的框架。iOS10苹果对CoreData进一步进行了封装,而且效率更高!相关类的简单介绍:
NSManagedObjectModel 模型对象:添加实体的属性,建立属性之间的关系
NSPersistentStoreCoordinator 数据库的助理:设置数据存储的名字,位置,存储方式,和存储时机
NSManagedObjectContext 生成上下文,关联数据库助理,插入数据,查询数据,删除数据,更新数据
NSPersistentContainer (iOS10之后才能使用)一个容器,封装了应用程序中的CoreData Stack(核心数据栈堆)
2、创建CoreData
1)创建CoreData操作源文件 xxxx.xcdatamodeld
方法一:创建工程时直接勾选 Use Core Data 选项
方法二:手动创建
通过New File --->>iOS (Core Data) Data Model路径创建!
2)创建实体(model)
通过导航栏Editor--->>Create NSManagedObject Subclass--->>选择表 --->> 选择model
》》》》》》
然后会生成四个文件如图所示:
注意:1、右边可以选择创建实体类语言Objective-C或者Swift;
2、创建之后工程报错CoreData手动创建托管对象子类时报错解决方法;
3、简单使用CoreData
方法一:在iOS10之前使用详情
自动创建CoreData时,在AppDelegate.m文件中有系统封装的方法如下:(手动创建就是把方法复制一遍)
- (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. [self saveContext]; } #pragma mark - Core Data stack //NSManagedObject(被管理的数据记录) //数据库中的表格记录 //NSEntityDescription(实体结构) //相当于表格结构 //NSFetchRequest(数据请求) //相当于查询语句 //.xcdatamodel文件,用数据模型编辑器编辑 //编译后为.momd或.mom文件 //存储路径 - (NSURL *)applicationDocumentsDirectory { NSLog(@"===%lu",(unsigned long)NSDocumentDirectory); return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; } //创建模型对象 //作用:添加实体的属性,建立属性之间的关系 //操作方法:视图编辑器,或代码 - (NSManagedObjectModel *)managedObjectModel { if (_managedObjectModel != nil) { return _managedObjectModel; } NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"CoreDataTest" withExtension:@"momd"]; _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; return _managedObjectModel; } //创建数据库助理 //作用:设置数据存储的名字,位置,存储方式,和存储时机 - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { if (_persistentStoreCoordinator != nil) { return _persistentStoreCoordinator; } _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreDataTest.sqlite"]; NSError *error = nil; NSString *failureReason = @"There was an error creating or loading the application's saved data."; if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { NSMutableDictionary *dict = [NSMutableDictionary dictionary]; dict[NSLocalizedDescriptionKey] = @"Failed to initialize the application's saved data"; dict[NSLocalizedFailureReasonErrorKey] = failureReason; dict[NSUnderlyingErrorKey] = error; error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict]; NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } return _persistentStoreCoordinator; } //生成上下文,关联数据库助理 //作用:插入数据,查询数据,删除数据,更新数据 - (NSManagedObjectContext *)managedObjectContext { if (_managedObjectContext != nil) { return _managedObjectContext; } NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; if (!coordinator) { return nil; } _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; [_managedObjectContext setPersistentStoreCoordinator:coordinator]; return _managedObjectContext; } #pragma mark - Core Data Saving support //保存 - (void)saveContext { NSManagedObjectContext *managedObjectContext = self.managedObjectContext; if (managedObjectContext != nil) { NSError *error = nil; if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) { NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } } }
具体的增加、删除、修改、查找数据操作如下:(一般情况下使用CoreData都会自己把上面方法封装,组成一个CoreData的工具类)
//添加一条数据 - (void)addData{ Student *newEintity = [NSEntityDescription insertNewObjectForEntityForName:Model_Name inManagedObjectContext:self.managedObjectContext]; newEintity.name = @"张三"; newEintity.age = @"13"; [self saveContext]; } //删除一条数据 - (void)deleData{ NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:Model_Name]; NSPredicate *predic = [NSPredicate predicateWithFormat:@"name = %@",@"张三"]; request.predicate = predic; NSArray *arr = [self.managedObjectContext executeFetchRequest:request error:nil]; if (arr.count>0) { [self.managedObjectContext deleteObject:arr.firstObject]; [self saveContext]; } } //删除和修改数据时先查找 //改变一条数据 - (void)exchangeData{ NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:Model_Name]; NSPredicate *predic = [NSPredicate predicateWithFormat:@"name = %@",@"张三"]; request.predicate = predic; NSArray *arr = [self.managedObjectContext executeFetchRequest:request error:nil]; if (arr.count>0) { Student *objc = (Student *)arr.firstObject; objc.name = @"李四"; objc.age = @"43"; [self saveContext]; } }
方法二:iOS10之后,苹果添加了一个NSPersistentContainer类,将之前方法进行了封装。这时候AppDelegate.m中的方法只有:
- (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. // Saves changes in the application's managed object context before the application terminates. [self saveContext]; } #pragma mark - Core Data stack @synthesize persistentContainer = _persistentContainer; - (NSPersistentContainer *)persistentContainer { // The persistent container for the application. This implementation creates and returns a container, having loaded the store for the application to it. @synchronized (self) { if (_persistentContainer == nil) { _persistentContainer = [[NSPersistentContainer alloc] initWithName:@"TestCoreData"]; [_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) { if (error != nil) { NSLog(@"Unresolved error %@, %@", error, error.userInfo); abort(); } }]; } } return _persistentContainer; } #pragma mark - Core Data Saving support - (void)saveContext { NSManagedObjectContext *context = self.persistentContainer.viewContext; NSError *error = nil; if ([context hasChanges] && ![context save:&error]) { // Replace this implementation with code to handle the error appropriately. // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. NSLog(@"Unresolved error %@, %@", error, error.userInfo); abort(); } }
具体的增加、删除、修改、查找数据操作如下:
//添加一条数据 - (void)addData{ Student *newEintity = [NSEntityDescription insertNewObjectForEntityForName:Model_Name inManagedObjectContext:self.delegate.persistentContainer.viewContext]; newEintity.name = @"张三"; newEintity.age = @"13"; [self.delegate saveContext]; } //删除一条数据 - (void)deleData{ NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:Model_Name]; NSPredicate *predic = [NSPredicate predicateWithFormat:@"name = %@",@"张三"]; request.predicate = predic; NSArray *arr = [self.delegate.persistentContainer.viewContext executeFetchRequest:request error:nil]; if (arr.count>0) { [self.delegate.persistentContainer.viewContext deleteObject:arr.firstObject]; [self.delegate saveContext]; } } //删除和修改数据时先查找 //改变一条数据 - (void)exchangeData{ NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:Model_Name]; NSPredicate *predic = [NSPredicate predicateWithFormat:@"name = %@",@"张三"]; request.predicate = predic; NSArray *arr = [self.delegate.persistentContainer.viewContext executeFetchRequest:request error:nil]; if (arr.count>0) { Student *objc = (Student *)arr.firstObject; objc.name = @"李四"; objc.age = @"43"; [self.delegate saveContext]; } }
4、关于iOS10新类NSPersistentContainer的简介
//版本要求 API_AVAILABLE(macosx(10.12),ios(10.0),tvos(10.0),watchos(3.0)) @interface NSPersistentContainer : NSObject { #if (!__OBJC2__) //将之前的属性直接封装 @private id _name; NSManagedObjectContext *_viewContext; id _storeCoordinator; id _storeDescriptions; #endif } /**类方法创建NSPersistentContainer * name:表示保存的数据库文件名称 * 使用此方法创建NSPersistentContainer,默认模型文件名称为name */ + (instancetype)persistentContainerWithName:(NSString *)name; /**类方法创建NSPersistentContainer * name:表示保存的数据库文件名称 * model:对象管理模型 */ + (instancetype)persistentContainerWithName:(NSString *)name managedObjectModel:(NSManagedObjectModel *)model; //返回沙盒中存储数据库的文件夹URL路径,这个文件夹是动态创建的(Library->Application Support) + (NSURL *)defaultDirectoryURL; //当前NSPersistentContainer容器的名称 @property (copy, readonly) NSString *name; //自动生成的管理对象上下文,这个上下文默认的操作类型是NSMainQueueConcurrencyType主线程 @property (strong, readonly) NSManagedObjectContext *viewContext; //对象管理模型 @property (strong, readonly) NSManagedObjectModel *managedObjectModel; //存储调度器 @property (strong, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator; //存储器描述数组 @property (copy) NSArray<NSPersistentStoreDescription *> *persistentStoreDescriptions; // 和上面初始化一样 - (instancetype)initWithName:(NSString *)name; - (instancetype)initWithName:(NSString *)name managedObjectModel:(NSManagedObjectModel *)model NS_DESIGNATED_INITIALIZER; //加载存储器,此方法必须要调用,否则无法存储数据 //block中NSPersistentStoreDescription用于描述生成的存储器信息,如:数据库文件路径、存储类型等 NSError用于描述加载存储器是否成功或失败信息 - (void)loadPersistentStoresWithCompletionHandler:(void (^)(NSPersistentStoreDescription *, NSError * _Nullable))block; //返回一个基于多线程的管理对象上下文,我们无需关心多线程的内部实现以及线程安全,由NSPersistentContainer新创建一个 //调用这个方法之后,对返回的上下文做一些数据的处理都是在子线程中完成的,可以用于处理对数据库进行大量数据操作的场景 - (NSManagedObjectContext *)newBackgroundContext NS_RETURNS_RETAINED; //使用存储调度器快速在多线程中操作数据库,效率非常高 - (void)performBackgroundTask:(void (^)(NSManagedObjectContext *))block;