iOSDay37数据处理之CoreData

来源:互联网 发布:最优化可行方向 编辑:程序博客网 时间:2024/05/24 06:49
1. CoreData数据库框架的优势

 1> CoreData历史

  CoreData数据持久化框架是Cocoa API 的一部分,首次在iOS5版本的系统中出现,它允许按照实体-属性-值模型组织数据,并以XML、二级制文件或者SQLite数据文件的格式持久化数据。

  CoreData主要提供对象 --- 关系映射(ORM)功能,把OC对象转化为数据保存到文件,也可以数据转化为OC对象。

 2> CoreData数据库与Sqlite数据库的比较

  Sqlite:

  • 基于C接口,需要使用sql语句,但是代码较为繁琐

  • 在处理大量数据时,表关系更为直观

  • 在OC中不是可视化的

  • 可以跨平台使用(iOS和安卓)

  CoreData:

  • 可视化,有undo/redo能力

  • 可以实现多种文件格式NSSQLiteStoreTypeNSBinaryStoreTypeNSInMemoryStoreTypeNSXMLStoreType

  • 苹果官方API支持,与iOS结合更紧密

  • 不能跨平台使用,只支持iOS

 3> CoreData核心对象及关系实例(以一个餐馆为例)

  

2. CoreData数据库框架的核心对象

 1> 被管理对象上下文(NSManagedObjectContext)

  NSManagedObjectContext:被管理对象上下文,CoreData中用于操作和使用数据,负责应用和数据库之间的交互,可以进行增、删、改、查

  数据的保存需要 NSManagedObjectContext 进行 save 操作

  数据的查询需要 NSManagedObjectContext 进行 executeFetchRequest 操作(返回值是数组)

  CoreData提供的是对象关系映射,NSManagedObjectContext操作的都是NSManagedObject对象

 2> 被管理对象相关类

  NSManagedObjectModel:被管理对象模型,管理多个对象

  NSManagedObject:被管理对象,CoreData返回的数据类型,被管理的对象是根据是根据实体描述生成的

  NSEntityDescription:实体描述类,根据实体创建被管理对象,可以映射出对象

  Entity:实体类,实体是对文件数据的描述。被管理对象表示实体,实体包含名称,属性(字段)和关系,实体的名称通常和被管理对象名一致

 3> 持久化存储和存储文件

  数据连接器类:NSPersistentStoreCoordinator,持久化存储调节器,它想要去SQLite数据库中拿数据必须通过NSPersistentStore

  NSPersistentStore:持久化存储,是对实际文件的一种。Objective-C表示方式,一个被封装好的底层类,用于存储数据

  存储文件:用来存储和管理数据的文件,iOS支持4种存储类型:NSSQLiteStoreType、NSBinaryStoreType、NSInMemoryStoreType、NSXMLStoreType

 4> 数据查询

  NSFetchRequest:查询请求,可以做排序操作,也可以使用谓词

  NSManagedObjectModel根据NSFetchRequest查询数据,以数组形式返回,数组中包含被管理对象(NSManagedObject

  NSSortDescriptor:排序操作

3. CoreData数据库的简单操作 

 1> 创建步骤

  ① 创建带有CoreData数据库的工程

  

  ② 创建实体类与属性

  ③ 切换可视化关系图

  

 

  ④ 创建实例类

    

 2> CoreData上下文(NSManagedObjectContext)的创建

  创建NSManagedObjectContext 这个类的对象 一般都用从AppDelegate里面的拿过来用,不用单独创建,创建工程勾选 use CoreData 这些代码AppDelegate就创建好

 1 @interface ViewController () 2  3 #pragma mark - 第二步:声明属性【声明管理对象上下文】(Sqlite中是声明一个存储数据路径的属性) 4 @property (nonatomic, strong) NSManagedObjectContext *managedObjectContext; 5  6 @end 7  8 @implementation ViewController 9 10 #pragma mark - 懒加载(与以前有所区别)11 - (NSManagedObjectContext *)managedObjectContext12 {13     // 因为在Appdelegate中已经实现过了,所以这里是从Appdelegate中去获取14     if (!_managedObjectContext) {15         16         // 获取appDelegate对象,使用系统的单例方法创建17         AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;18         19         _managedObjectContext = appDelegate.managedObjectContext;20     }21     return _managedObjectContext;22 }23 24 @end

 3> AppDelegate创建好的代码解析(详解请看注释)

  AppDelegate.h

 1 #import <UIKit/UIKit.h> 2 #import <CoreData/CoreData.h> 3  4 @interface AppDelegate : UIResponder <UIApplicationDelegate> 5  6 @property (strong, nonatomic) UIWindow *window; 7  8 /// 管理数据库上下文的对象,可以进行增、删、改、查 9 @property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;10 11 /// 管理数据库中的对象(对象模型),可以将工程中的对象合并(为了更加方便的生成数据库中的表)12 @property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;13 14 /// 数据库持久化协调器,实际的工作都是由它来做的15 @property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;16 17 - (void)saveContext;18 - (NSURL *)applicationDocumentsDirectory;19 20 @end

  AppDelegate.m

  1 #import "AppDelegate.h"  2   3 @interface AppDelegate ()  4   5 @end  6   7 @implementation AppDelegate  8   9 #pragma mark - Core Data stack 10  11 @synthesize managedObjectContext = _managedObjectContext; 12 @synthesize managedObjectModel = _managedObjectModel; 13 @synthesize persistentStoreCoordinator = _persistentStoreCoordinator; 14  15 // 返回coreData存储的路径 16 - (NSURL *)applicationDocumentsDirectory { 17      18     // 5. 打印coreData存储的路径【Sqlite的dbPath字符串路径】 19     NSLog(@"filePath = %@", [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]); 20      21     // 返回coreData存储的路径 22     return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; 23 } 24  25 #pragma mark - 获取管理对象 26 - (NSManagedObjectModel *)managedObjectModel { 27      28     if (_managedObjectModel != nil) { 29         return _managedObjectModel; 30     } 31      32     // 从应用程序中加载模型文件 33     // momd 是编译后的文件后缀 34     NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"UISenior_4_1_CoreData" withExtension:@"momd"]; 35      36     _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];// 代表的就是刚刚创建的实体 37      38     return _managedObjectModel; 39 } 40  41 #pragma mark - 数据持久化协调器(真正干活的) 42 // persistentStoreCoordinator的getter方法 43 - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { 44      45     if (_persistentStoreCoordinator != nil) { 46         return _persistentStoreCoordinator; 47     } 48  49     // 连接器对象关联的实体模型 50     _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; 51      52     // 定义数据存储的路径 53     NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"UISenior_4_1_CoreData.sqlite"]; 54      55     NSError *error = nil; 56     NSString *failureReason = @"There was an error creating or loading the application's saved data."; 57      58     // NSSQLiteStoreType这个参数决定文件存储的形式(sqlite、XML、二进制等) 59     if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { 60         // 返回可能出现的错误信息 61         NSMutableDictionary *dict = [NSMutableDictionary dictionary]; 62         dict[NSLocalizedDescriptionKey] = @"Failed to initialize the application's saved data"; 63         dict[NSLocalizedFailureReasonErrorKey] = failureReason; 64         dict[NSUnderlyingErrorKey] = error; 65         error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict]; 66  67         // abort()会导致应用程序生成一个崩溃日志和终止。虽然它可能是有用的在开发过程中, 但是你不应该使用这个函数在运行的应用程序中。 68         NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 69         abort(); 70     } 71      72     return _persistentStoreCoordinator; 73 } 74  75 #pragma mark - 获取数据库上下文 76 // managedObjectContext的getter方法 77 - (NSManagedObjectContext *)managedObjectContext { 78      79     if (_managedObjectContext != nil) { 80         return _managedObjectContext; 81     } 82      83     // 创建数据持久化协调器 84     NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 85      86     if (!coordinator) { 87         return nil; 88     } 89      90     // 创建managedObjectContext对象 91     // ConcurrencyType 并发类型,是一个枚举值 92     // NSMainQueueConcurrencyType 主队列并发类型(2) 93     // NSPrivateQueueConcurrencyType 私有队列并发类型(1) 94     // NSConfinementConcurrencyType 限制并发类型(0) 95     _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 96      97     // 数据连接器 关联 被管理上下文 98     [_managedObjectContext setPersistentStoreCoordinator:coordinator]; 99     100     return _managedObjectContext;101 }102 103 #pragma mark - Core Data Saving support104 105 - (void)saveContext {106     NSManagedObjectContext *managedObjectContext = self.managedObjectContext;107     if (managedObjectContext != nil) {108         // 同上面的错误处理109         NSError *error = nil;110         if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {111             112             NSLog(@"Unresolved error %@, %@", error, [error userInfo]);113             abort();114         }115     }116 }117 118 @end

 4> 添加对象(详解请看注释)

 1 - (void)addPerson 2 { 3     // 添加的步骤 4     // 1. 创建Person实体对象,然后开始"context",让它做好准备,将这个对象添加到数据库 5      6     /** 7      *  实例对象有两种[初始化实体对象需要借用NSEntityDescription] 8      */ 9     10     // 第一种:11 //    Person *per = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:self.managedObjectContext];12     // 第二种:13     // 先创建一个实体14     NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:self.managedObjectContext];15     // 创建Person对象16     Person *per = [[Person alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:self.managedObjectContext];17     18     // 2. 给对象属性赋值19     per.personName = @"MBBoy";20     per.personGender = @"Unkown";21     per.personAge = @10;22 23     // 3. 将对象存入数据库24     BOOL result = [_managedObjectContext save:nil];25     26     per.personCar = carSet;27     28     // 4. 判断是否插入成功(在AppDelegate中打印地址)29     if (result) {30         NSLog(@"添加数据成功");31     } else {32         NSLog(@"添加数据失败");33     }34 }

 5> 删除对象(详解请看注释)

 1 - (void)deletePerson 2 { 3     // 1. 实体化请求类【查询】 4     NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Person"]; 5      6     // 2. 获取删除的条件(NSPredicate) 7     request.predicate = [NSPredicate predicateWithFormat:@"personName = 'MBBoy'"]; 8      9     // 3. 由context根据删除条件的请求去具体进行删除操作10     NSArray *resultArray = [self.managedObjectContext executeFetchRequest:request error:nil];11     12     // 为了代码的严密需要判断resultArray中是否有值13     if (0 == resultArray.count) {14         NSLog(@"未找到删除对象");15     } else {16         // 4. 遍历搜索出来结果17         for (Person *per in resultArray) {18             // 删除查询到相关的人的信息19             [self.managedObjectContext deleteObject:per];20         }21         22         // 5. 进行删除结果的判断,保存后删除操作才会写入文件23         BOOL result = [_managedObjectContext save:nil];24         if (result) {25             NSLog(@"删除数据成功");26         } else {27             NSLog(@"删除数据失败");28         }29     }30 }

 6> 更改对象(详解请看注释)

 1 - (void)updatePerson 2 { 3     // 1. 实体化请求类【查询】 4     NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Person"]; 5      6     // 2. 设置查询的条件 7     request.predicate = [NSPredicate predicateWithFormat:@"personName = 'MBBoy'"]; 8      9     // 3. 由context根据查询条件的请求去具体进行更新操作10     NSArray *resultArray = [self.managedObjectContext executeFetchRequest:request error:nil];11     12     // 为了代码的严密需要判断resultArray中是否有值13     if (0 == resultArray.count) {14         NSLog(@"未找到更改对象,请检查谓词条件!");15     } else {16         // 4. 遍历搜索结果17         for (Person *per in resultArray) {18             19             // 更新查询到相关的人的信息20             per.personName = @"小强";21             per.personGender = @"卵男";22             per.personAge = @38;23         }24         25         // 5. 进行删除结果的判断26         BOOL result = [_managedObjectContext save:nil];27         if (result) {28             NSLog(@"更改数据成功");29         } else {30             NSLog(@"更改数据失败");31         }32     }33 }

 7> 查询对象(详解请看注释)

 1 - (void)selectPerson 2 { 3     // 1. 实体化请求类【查询】 4     NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Person"]; 5      6     // 2. 设置查询的条件 7     request.predicate = [NSPredicate predicateWithFormat:@"personName like '*B*'"]; 8      9     // 3. 根据管理对象上下文执行相关的操作10     NSArray *resultArray = [self.managedObjectContext executeFetchRequest:request error:nil];11     12     if (0 == resultArray.count) {13         NSLog(@"未找到查询对象,请检查谓词条件!");14     } else {15         for (Person *per in resultArray) {16             NSLog(@"name = %@, gender = %@, age = %@", per.personName, per.personGender, per.personAge);17         }18     }19 }

  补: 查询结果的排序

1     // 设置排序方式2     NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"address" ascending:NO];3     request.sortDescriptors = @[sort];

4. CoreData数据库表关联操作 

 1> 添加表关系可视化操作

  Car数据库与Person数据库建立关联:

  

 Person数据库与Car数据库建立关联: 

   

 2> 添加表关系代码操作

 1     // 创建Person对象 2     Person *per = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:self.managedObjectContext]; 3     // 2. 给对象属性赋值 4     per.personName = @"MBBoy"; 5     per.personGender = @"Unkown"; 6     per.personAge = @10; 7      8     ///// 将车的对象通过实体描述类创建出来 9     Car *audiCar = [NSEntityDescription insertNewObjectForEntityForName:@"Car" inManagedObjectContext:self.managedObjectContext];10     11     audiCar.price = @300000;12     audiCar.color = @"白色";13     audiCar.brand = @"奥迪A7";14     15     Car *benchiCar = [NSEntityDescription insertNewObjectForEntityForName:@"Car" inManagedObjectContext:self.managedObjectContext];16     17     benchiCar.price = @500000;18     benchiCar.color = @"红色";19     benchiCar.brand = @"奔驰SUV";20     21     // 将两辆车放到集合中存储,然后进行赋值22     NSSet *carSet = [NSSet setWithObjects:audiCar, benchiCar, nil];23     24     // 3. 将对象存入数据库25     BOOL result = [_managedObjectContext save:nil];26     27     // 建立一对多关系28     per.personCar = carSet;29 30     // 4. 判断是否插入成功(在AppDelegate中打印地址)31     if (result) {32         NSLog(@"添加数据成功");33     } else {34         NSLog(@"添加数据失败");35     }

 

  补: 一对多表关系时CoreData自动生成基本操作方法

1 // 添加人与一辆车之间的关系2 - (void)addPersonCarObject:(NSManagedObject *)value;3 // 删除人与一辆车之间的关系4 - (void)removePersonCarObject:(NSManagedObject *)value;5 // 添加人与一组车之间关系6 - (void)addPersonCar:(NSSet<NSManagedObject *> *)values;7 // 删除人与一组车之间关系8 - (void)removePersonCar:(NSSet<NSManagedObject *> *)values;

  注:此处只是表间关系删除,并不会删除文件内数据

 

5. CoreData数据库数据的迁移

 1> 概述

   CoreData 支持随着App开发演进而带来的对象模型(NSManagedObjectModel)升级或修改的管理。模型的改变将导致不兼容(或不能打开)以前版本创建的存储。如果你要改变你的模型,你就必须要改变现有存储中的数据 - 即数据存储格式(store format)——这被称为数据迁移(migration)

 2> 数据迁移的三个阶段

  • 创建基于源实例对象的目标实例对象;

  

 

  • 重新建立联系;

  • 验证与保存;

0 0
原创粉丝点击