iOS开发之Core Data数据存储
2015-12-14 15:31
666 查看
Core Data是iOS5之后才出现的一个框架,它提供了对象-关系映射(ORM)的功能即能够将OC对象转化成数据,保存在SQLite数据库文件中,也能够将保存在数据库中的数据还原成OC对象。
传统的数据库要把数据写到数据库,而且要写SQL语句 Core Data 就避免了写SQL语句的麻烦了
CoreData底层的持久化存储方式可以是SQLite数据库,也可以是XML文件,甚至可以直接以内存作为持久化存储设备(如果选用该存储方式,那么应用重启时数据会丢失)。
CoreData的核心概念是实体。实体是由Core Data管理的模型对象,它必须是NSManagedObject类或其子类的实例。实体与实体之间存在1-1、1-N、N-N的关联关系。整个应用的所有实体以及实体之间的关联关系被称为托管对象模型。
CoreData的核心对象是托管对象上下文(NSManagedObjectContext,有时简称上下文),所有实体都处于托管对象上下文管理中,Core Data应用对实体所做的任何增、删、改、查操作都必须通过托管对象上下文来完成。
NSManagedObjectContext底层又与持久化存储协调器(NSPersistentStoreCoordinator)衔接。持久化存储协调器负责管理底层的存储形式,比如利用SQLite存储。
下面来总结Core Data中的核心API:
1. 实体(NSManagedObject):代表实体。实体必须是该类或该类的子类
2. 托管对象模型(NSManagedObjectModel):该对象负责管理整个应用的所有实体以及实体之间的关联关系。
3. 持久化存储协调器(NSpersistentStoreCoordinator):负责管理底层的存储方式,如利用SQLite存储。
4. 托管对象上下文(NSManagedObjectContext):对实体做的增、删、改、查操作都必须通过托管对象上下文来完成。
5. 实体描述(NSEntityDescription):该对象代表了关于某个实体的描述信息。从某种角度来说,该对象相当于实体的抽象。
6. 获取请求(NSfetchRequest):该对象封装了查询实体的请求,包括程序需要查询哪些实体、查询条件、排序规则等。
下面介绍一下使用Core Data的步骤:
1. 创建NSManageObjectModel对象来加载管理应用的托管对象模型。
2. 以NSManageObjectModel对象为基础,根据实际创建NSPersistentStoreCoordinator对象,该对象确定Core Data的底层存储形式。
3. 以NSManageObjectModel对象为基础,创建NSmanagedObjectContext对象,该对象是Core Data进行持久化访问的核心对象。
4. 利用获取实例(NSFectRequest)再调用NSmanagedObjectContext的executeFetchRequest:error:方法执行查询,找到符合条件的实体,再进行执行增、删、改、查操作,然后调用NSmanagedObjectContext对象的save:方法将修改白村到底层存储设备。
下面我们还是来通过存储学生信息为例,来讲解CoreData的简单使用。
新建项目,勾选Use Core Data复选框,我这里的项目名为:01-CoreData
create之后,会在项目导航区看到下图文件
还会在appDelegate类中发现多了几个属性和方法,如下:
appDelegate.h
appDelegate.m
并且在应用的代理方法中有:(当应用退出后,会保存上下文的修改)
点击.xcodemodeld文件,在工作区会出现如图所示界面
点击左下角add Entity按钮添加实体
然后在ENTITIES区会出现如图所示实体,再重命名实体名,我这里重命名为:StudentEntity
在该实体的右侧会出现添加属性界面,点击添加属性
属性添加完之后,点击xcode导航栏上的Editor -> Create NSManageObject Subclass自动创建实体类,如下:
这些准备工作做好以后,我们就可以向数据库_1_CoreData.sqlite中进行数据的增、删、该、查操作了。
添加学生信息:
点击添加按钮,将学生信息插入数据库中(这里不考虑重复插入)
打印结果:
现在我们向数据库中多插入几条数据,然后来做查询操作,看看数据库中有没有数据。查询操作如下:
打印出来看看,我们刚刚添加的多条学生信息
结果就是我们添加的学生,证明我们的数据已经添加到数据库中了。
我们先来删除指定姓名(如:shx1)的学生信息:(数据库中所有叫shx1的学生会全部删除)
输入要删除的学生姓名:shx1打印结果:
我们再查询所有学生信息,并打印,看看shx1还在不在,点击查询:
姓名叫shx1的学生没有了,证明我们已经删除了。
现在我们来修改某个学生(比如:shx5)的年龄。(原shx5的年龄从上面指定为22,现在我们将他的年龄改为100,数据库中所有叫shx5的学生的年龄都会被改成100)。
姓名输入shx5,年龄输入100,打印结果:
我们查询所有的学生信息,并打印出来,看看shx5的年龄是不是100。
姓名叫shx5的学生的年龄已经改为100了,证明我们的数据库操作是正确的。
以上是关于Core Data的简单使用,更进一步的使用我也在学习中。
传统的数据库要把数据写到数据库,而且要写SQL语句 Core Data 就避免了写SQL语句的麻烦了
CoreData底层的持久化存储方式可以是SQLite数据库,也可以是XML文件,甚至可以直接以内存作为持久化存储设备(如果选用该存储方式,那么应用重启时数据会丢失)。
CoreData的核心概念是实体。实体是由Core Data管理的模型对象,它必须是NSManagedObject类或其子类的实例。实体与实体之间存在1-1、1-N、N-N的关联关系。整个应用的所有实体以及实体之间的关联关系被称为托管对象模型。
CoreData的核心对象是托管对象上下文(NSManagedObjectContext,有时简称上下文),所有实体都处于托管对象上下文管理中,Core Data应用对实体所做的任何增、删、改、查操作都必须通过托管对象上下文来完成。
NSManagedObjectContext底层又与持久化存储协调器(NSPersistentStoreCoordinator)衔接。持久化存储协调器负责管理底层的存储形式,比如利用SQLite存储。
下面来总结Core Data中的核心API:
1. 实体(NSManagedObject):代表实体。实体必须是该类或该类的子类
2. 托管对象模型(NSManagedObjectModel):该对象负责管理整个应用的所有实体以及实体之间的关联关系。
3. 持久化存储协调器(NSpersistentStoreCoordinator):负责管理底层的存储方式,如利用SQLite存储。
4. 托管对象上下文(NSManagedObjectContext):对实体做的增、删、改、查操作都必须通过托管对象上下文来完成。
5. 实体描述(NSEntityDescription):该对象代表了关于某个实体的描述信息。从某种角度来说,该对象相当于实体的抽象。
6. 获取请求(NSfetchRequest):该对象封装了查询实体的请求,包括程序需要查询哪些实体、查询条件、排序规则等。
下面介绍一下使用Core Data的步骤:
1. 创建NSManageObjectModel对象来加载管理应用的托管对象模型。
2. 以NSManageObjectModel对象为基础,根据实际创建NSPersistentStoreCoordinator对象,该对象确定Core Data的底层存储形式。
3. 以NSManageObjectModel对象为基础,创建NSmanagedObjectContext对象,该对象是Core Data进行持久化访问的核心对象。
4. 利用获取实例(NSFectRequest)再调用NSmanagedObjectContext的executeFetchRequest:error:方法执行查询,找到符合条件的实体,再进行执行增、删、改、查操作,然后调用NSmanagedObjectContext对象的save:方法将修改白村到底层存储设备。
下面我们还是来通过存储学生信息为例,来讲解CoreData的简单使用。
新建项目,勾选Use Core Data复选框,我这里的项目名为:01-CoreData
create之后,会在项目导航区看到下图文件
还会在appDelegate类中发现多了几个属性和方法,如下:
appDelegate.h
#import <UIKit/UIKit.h> #import <CoreData/CoreData.h> @interface AppDelegate : UIResponder <UIApplicationDelegate> @property (strong, nonatomic) UIWindow *window; /** * 托管对象上下文 */ @property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext; /** * 托管对象模型 */ @property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel; /** * 持久化存储协调器 */ @property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator; /** * 保存上下文修改 */ - (void)saveContext; /** * 获取Document的URL路径 */ - (NSURL *)applicationDocumentsDirectory; @end
appDelegate.m
#pragma mark - Core Data stack @synthesize managedObjectContext = _managedObjectContext; @synthesize managedObjectModel = _managedObjectModel; @synthesize persistentStoreCoordinator = _persistentStoreCoordinator; /** * 获取Document的URL路径 */ - (NSURL *)applicationDocumentsDirectory { return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; } /** * 初始化托管对象模型(实体以及实体之间的关联关系) */ - (NSManagedObjectModel *)managedObjectModel { if (_managedObjectModel != nil) { return _managedObjectModel; } // 获取实体模型文件对应的URL NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"_1_CoreData" withExtension:@"momd"]; // 根据URL创建并初始化托管模型对象 _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; return _managedObjectModel; } /** * 初始化持久化存储协调器(Core Data底层的存储形式) */ - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { if (_persistentStoreCoordinator != nil) { return _persistentStoreCoordinator; } // 以托管模型对象创建并初始化协调器 _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; // 获取SQlLite数据库的存储目录 NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"_1_CoreData.sqlite"]; NSError *error = nil; NSString *failureReason = @"There was an error creating or loading the application's saved data."; // 设置底层数据存储机制为SQLite数据库,如果设置失败则返回错误信息 if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { // Report any error we got.(设置错误信息) 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(); } } }
并且在应用的代理方法中有:(当应用退出后,会保存上下文的修改)
- (void)applicationWillTerminate:(UIApplication *)application { // Saves changes in the application's managed object context before the application terminates. [self saveContext]; }
点击.xcodemodeld文件,在工作区会出现如图所示界面
点击左下角add Entity按钮添加实体
然后在ENTITIES区会出现如图所示实体,再重命名实体名,我这里重命名为:StudentEntity
在该实体的右侧会出现添加属性界面,点击添加属性
属性添加完之后,点击xcode导航栏上的Editor -> Create NSManageObject Subclass自动创建实体类,如下:
这些准备工作做好以后,我们就可以向数据库_1_CoreData.sqlite中进行数据的增、删、该、查操作了。
添加学生信息:
点击添加按钮,将学生信息插入数据库中(这里不考虑重复插入)
/** * 添加学生信息 */ - (IBAction)addClick { // 利用NSEntityDescription获取StudentEntity实体 StudentEntity *stu = [NSEntityDescription insertNewObjectForEntityForName:@"StudentEntity" inManagedObjectContext:[AppDelegate shareAppDelegate].managedObjectContext]; stu.name = self.nameTextField.text; stu.age = [NSNumber numberWithInteger:[self.ageTextField.text integerValue]]; stu.sex = [NSNumber numberWithInt:[self.sexTextField.text intValue]]; NSError *error = nil; [[AppDelegate shareAppDelegate].managedObjectContext save:&error]; if (error) { NSLog(@"添加失败"); }else { NSLog(@"添加成功"); } }点击添加按钮后,会在应用沙盒中发现下图文件:
打印结果:
现在我们向数据库中多插入几条数据,然后来做查询操作,看看数据库中有没有数据。查询操作如下:
/** * 查询所有学生信息,并打印 */ - (IBAction)queryClick { // 得到获取数据的请求对象 NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"StudentEntity"]; // 排序规则(查询结果按年龄降序排序) NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO]; request.sortDescriptors = @[sort]; // 执行查询 NSError *error = nil;// 错误信息 NSArray *result = [[AppDelegate shareAppDelegate].managedObjectContext executeFetchRequest:request error:&error]; if (error) { NSLog(@"查询操作失败"); }else { if (result.count <= 0) { NSLog(@"无学习信息"); }else { NSLog(@"打印学生信息:"); for (StudentEntity *stu in result) { NSLog(@"姓名:%@,年龄:%lu,性别:%d", stu.name, stu.age.integerValue, stu.sex.intValue); } } } }
打印出来看看,我们刚刚添加的多条学生信息
结果就是我们添加的学生,证明我们的数据已经添加到数据库中了。
我们先来删除指定姓名(如:shx1)的学生信息:(数据库中所有叫shx1的学生会全部删除)
/** * 删除指定姓名的学生信息 */ - (IBAction)deleteClick { // 先遍历数据库,查询有无该学生信息,无该学生则不用执行删除操作 // 得到获取数据的请求对象 NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"StudentEntity"]; // 查询条件 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name = %@", self.deleteNameTextField.text]; request.predicate = predicate; // 排序规则(按年龄升序) NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO]; request.sortDescriptors = @[sort]; // 执行查询 NSError *error = nil;// 错误信息 NSArray *result = [[AppDelegate shareAppDelegate].managedObjectContext executeFetchRequest:request error:&error]; // 查询结果 if (error) { NSLog(@"查询操作失败"); }else { if (result.count) {// 有该学生信息,可执行删除操作 for (StudentEntity *stu in result) { // 删除学生信息 [[AppDelegate shareAppDelegate].managedObjectContext deleteObject:stu]; NSLog(@"删除成功"); } // 删除数据后,保存 NSError *saveError = nil; [[AppDelegate shareAppDelegate].managedObjectContext save:&saveError]; if (saveError) { NSLog(@"删除,保存失败"); }else { NSLog(@"删除,保存成功"); } }else { NSLog(@"无该学生信息"); } } }
输入要删除的学生姓名:shx1打印结果:
我们再查询所有学生信息,并打印,看看shx1还在不在,点击查询:
姓名叫shx1的学生没有了,证明我们已经删除了。
现在我们来修改某个学生(比如:shx5)的年龄。(原shx5的年龄从上面指定为22,现在我们将他的年龄改为100,数据库中所有叫shx5的学生的年龄都会被改成100)。
/** * 修改某个学生的年龄 */ - (IBAction)tureClick { // 先遍历数据库,查询有无该学生信息,无该学生则不能修改年龄 // 得到获取数据的请求对象 NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"StudentEntity"]; // 查询条件 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name = %@", self.updateNameTextField.text]; request.predicate = predicate; // 执行查询 NSError *error = nil;// 错误信息 NSArray *result = [[AppDelegate shareAppDelegate].managedObjectContext executeFetchRequest:request error:&error]; // 查询结果 if (error) { NSLog(@"查询操作失败"); }else { if (result.count) {// 有该学生信息,可执行修改操作 for (StudentEntity *stu in result) { // 修改学生信息 stu.age = [NSNumber numberWithInt:self.updateAgeTextField.text.intValue]; NSLog(@"修改成功"); } // 删除数据后,保存 NSError *saveError = nil; [[AppDelegate shareAppDelegate].managedObjectContext save:&saveError]; if (saveError) { NSLog(@"修改,保存失败"); }else { NSLog(@"修改,保存成功"); } }else { NSLog(@"无该学生信息"); } } }
姓名输入shx5,年龄输入100,打印结果:
我们查询所有的学生信息,并打印出来,看看shx5的年龄是不是100。
姓名叫shx5的学生的年龄已经改为100了,证明我们的数据库操作是正确的。
以上是关于Core Data的简单使用,更进一步的使用我也在学习中。
相关文章推荐
- iOS 硬件授权检测:定位服务、通讯录、日历、提醒事 项、照片、蓝牙共享、麦克风、相机等
- iOS键盘隐藏
- iOS 性能篇 - AutoLayout
- 理解 iOS 开发中 GCD 相关的同步(synchronization)\ 异步(asynchronization),串行(serial)\ 并行(concurrency)概念
- ios开发之实现提示框动画效果
- ios 下拉刷新 上拉更多
- iOS中的触摸事件和手势处理
- iOS 处理图片的一些小 Tip
- iOS 自定义九宫格,行、列可变
- fir.im Weekly - 94 个 iOS 开发资源推荐
- 关于目前自己iOS项目使用的第三方开源库
- iOS检查更新
- iOS 笔记-AFN使用中的遇到的问题
- fir.im Weekly - 94 个 iOS 开发资源推荐
- iOS 笔记-incompatible pointer types initializing 'NSMutableString *' with an expression of type 'NSString *'警告处理
- IOS NSString比较,截取,NSLog,NSRang,isEqualToString,stringWithFormat
- iOS ---清除缓存
- iOS 获取快递物流信息(GCD异步加载)
- IOS开发 判断是否是非法字符 例如表情符号
- iOS 开发判断应用是否连接WiFi,并跳转到设置中的WiFi设置页面。