iOS 数据持久化 -- Core Data (2)

来源:互联网 发布:淘宝代销商品怎么下单 编辑:程序博客网 时间:2024/04/27 11:53

iOS 数据持久化 --Core Data (2)

CoreData

1.Core Data 是数据持久化存储的最佳方式

2.数据最终的存储类型可以是:SQLite数据库,XML,二进制,内存里,或自定义数据类型

在Mac OS X 10.5Leopard及以后的版本中,开发者也可以通过继承NSPersistentStore类以创建自定义的存储格式

3.好处:能够合理管理内存,避免使用sql的麻烦,高效

4.构成:

(1)NSManagedObjectContext(被管理的数据上下文)

操作实际内容(操作持久层)

作用:插入数据,查询数据,删除数据

(2)NSManagedObjectModel(被管理的数据模型)

数据库所有表格或数据结构,包含各实体的定义信息

作用:添加实体的属性,建立属性之间的关系

操作方法:视图编辑器,或代码

(3)NSPersistentStoreCoordinator(持久化存储助理)

相当于数据库的连接器

作用:设置数据存储的名字,位置,存储方式,和存储时机

(4)NSManagedObject(被管理的数据记录)

相当于数据库中的表格记录

(5)NSFetchRequest(获取数据的请求)

相当于查询语句

(6)NSEntityDescription(实体结构)

相当于表格结构

(7)后缀为.xcdatamodeld的包

里面是.xcdatamodel文件,用数据模型编辑器编辑

编译后为.momd或.mom文件

5.依赖关系

二、基于SQLite数据库时,Core Data的简单使用

和SQLite的区别:只能取出整个实体记录,然后分解,之后才能得到实体的某个属性

1.构建流程

包括:创建数据上下文,创建数据模型,创建数据持久化存储助理

(1)若是新建的工程,选择空白应用程序,next

勾选Use Core Data选项

此时生成的工程文件AppDelegate中,会自动生成被管理的数据上下文等相关代码

(2)比如AppDelegate.h文件中,自动生成

@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;- (void)saveContext;- (NSURL *)applicationDocumentsDirectory;

方法saveContext表示:保存数据到持久层(数据库)

方法applicationDocumentsDirectory表示:应用程序沙箱下的Documents目录路径

(例如/var/mobile/Applications/5FG80A45-DFB5-4087-A1B1-41342A977E21/Documents/)

(3)比如AppDelegate.h文件中,自动生成

@synthesize managedObjectContext = __managedObjectContext;@synthesize managedObjectModel = __managedObjectModel;@synthesize persistentStoreCoordinator = __persistentStoreCoordinator;

保存数据到持久层

- (void)applicationWillTerminate:(UIApplication *)application{    [self saveContext];}
- (void)saveContext{    NSError *error = nil;    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;    if (managedObjectContext != nil) {        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);            abort();        }     }}

Documents目录路径

- (NSURL *)applicationDocumentsDirectory{    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];}

被管理的数据上下文

初始化的后,必须设置持久化存储助理

- (NSManagedObjectContext *)managedObjectContext{    if (__managedObjectContext != nil) {        return __managedObjectContext;    }    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];    if (coordinator != nil) {        __managedObjectContext = [[NSManagedObjectContext alloc] init];        [__managedObjectContext setPersistentStoreCoordinator:coordinator];    }    return __managedObjectContext;}

被管理的数据模型

初始化必须依赖.momd文件路径,而.momd文件由.xcdatamodeld文件编译而来

- (NSManagedObjectModel *)managedObjectModel{    if (__managedObjectModel != nil) {        return __managedObjectModel;    }    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"TestApp" withExtension:@"momd"];    __managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];    return __managedObjectModel;}

持久化存储助理

初始化必须依赖NSManagedObjectModel,之后要指定持久化存储的数据类型,默认的是NSSQLiteStoreType,即SQLite数据库;并指定存储路径为Documents目录下,以及数据库名称

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator{    if (__persistentStoreCoordinator != nil) {        return __persistentStoreCoordinator;    }    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"TestApp.sqlite"];    NSError *error = nil;    __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];    if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);        abort();    }        return __persistentStoreCoordinator;}

如果不是新工程,也可以自己写入相关代码

(4)此外还生成了TestApp.xcdatamodeld文件

(5)还自动链接了CoreData.framework

(6)在预编译头.pch文件中,加入导入了CoreData.h头文件

#import <CoreData/CoreData.h>

2.创建数据模型(数据模型编辑器操作)

(1)创建实体

选中.xcodedatamodel对象

在右边的数据模型编辑器的底部工具栏点击Add Entity添加实体

在最右侧栏对实体命名

(2)创建实体属性

选中实体,点击底部工具栏的Add Attribute添加属性

选中新添加的属性,对属性进行命名,并设置属性的数据类型Attribute Type

(3)为两个实体建立关系

选中一个实体,在底部工具栏点击Add Relationship添加关系

选中新关系,对关系添加名称,目标destination设置为另个实体

(4)建立返回关系

(当你建立一个目标关系,最好建立一个返回关系)

在另一个实体中建立一个关系并命名,设置目标对象为这之前的实体

并在Inverse属性选这之前的关系名称

(5)设置两个关系的删除规则Delete Rule,都为关联模式

关联模式cascade:其中一个数据被删除,另一个实体中的数据也会跟着删除

(6)最终两个对象的关系图为

切换Editor Stype按钮

会看到另一种编辑方式:

 3.插入数据

在AppDelegate.m的application:didFinishLaunchingWithOptions:方法里,调用自定义方法

insertCoreData插入数据,代码如下:

- (void)insertCoreData{    NSManagedObjectContext *context = [self managedObjectContext];        NSManagedObject *contactInfo = [NSEntityDescription insertNewObjectForEntityForName:@"ContactInfo" inManagedObjectContext:context];    [contactInfo setValue:@"name B" forKey:@"name"];    [contactInfo setValue:@"birthday B" forKey:@"birthday"];    [contactInfo setValue:@"age B" forKey:@"age"];        NSManagedObject *contactDetailInfo = [NSEntityDescription insertNewObjectForEntityForName:@"ContactDetailInfo" inManagedObjectContext:context];    [contactDetailInfo setValue:@"address B" forKey:@"address"];    [contactDetailInfo setValue:@"name B" forKey:@"name"];    [contactDetailInfo setValue:@"telephone B" forKey:@"telephone"];        [contactDetailInfo setValue:contactInfo forKey:@"info"];    [contactInfo setValue:contactDetailInfo forKey:@"details"];        NSError *error;    if(![context save:&error])    {        NSLog(@"不能保存:%@",[error localizedDescription]);    }}

创建数据上下文,调用insertNewObjectForName方法,创建两个数据记录NSManagedObject,然后就可以对之前数据模型编辑视图中定义的属性进行赋值。此时的数据只在内存中被修改,最后调用数据上下文的save方法,保存到持久层

4.查询数据

在调用了insertCoreData之后,可以调用自定的查询方法dataFetchRequest来查询插入的数据

- (void)dataFetchRequest{    NSManagedObjectContext *context = [self managedObjectContext];    NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];    NSEntityDescription *entity = [NSEntityDescription entityForName:@"ContactInfo" inManagedObjectContext:context];    [fetchRequest setEntity:entity];    NSError *error;    NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];    for (NSManagedObject *info in fetchedObjects) {        NSLog(@"name:%@", [info valueForKey:@"name"]);        NSLog(@"age:%@", [info valueForKey:@"age"]);        NSLog(@"birthday:%@", [info valueForKey:@"birthday"]);        NSManagedObject *details = [info valueForKey:@"details"];        NSLog(@"address:%@", [details valueForKey:@"address"]);         NSLog(@"telephone:%@", [details valueForKey:@"telephone"]);    }}

fetchRequest相当于sql查询语句的包装类,需要用setEntity方法,来指定具体查询的实体结构(表结构)

通过NSEntityDescription的entityForName方法来,返回指向该具体实体结构的指针

然后调用executeFetchRequest:error:方法,来执行查询操作,如果操作成功,则返回对应的数据记录数组

其中,可以通过NSManagedObject数据记录对象里关联的属性,查询另一个数据记录对象里的属性

5.数据模版

为每个实体生成一个NSManagedObject子类

上面设置数据和获取数据时,使用的是Key-Value方式,更好的方法是通过生成强类型的NSManagedObject的子类,通过类的成员属性来访问和获取数据

(1)在数据编辑器视图中选中实体对象,

选则file菜单,点击new,点击file...,选择Core Data项,选择NSManagedObject subclass,生成该实体同名的类,

继承于NSManagedObject

生成对应的ContactInfo.h文件

#import <Foundation/Foundation.h>#import <CoreData/CoreData.h>@class ContactDetailInfo;@interface ContactInfo : NSManagedObject@property (nonatomic, retain) NSString * age;@property (nonatomic, retain) NSString * birthday;@property (nonatomic, retain) NSString * name;@property (nonatomic, retain) ContactDetailInfo *details;@end

和ContactInfo.m文件

其中,@dynamic告诉编译器不做处理,使编译通过,其getter和setter方法会在运行时动态创建,由Core Data框架为此类属性生成存取方法

#import "ContactInfo.h"#import "ContactDetailInfo.h"@implementation ContactInfo@dynamic age;@dynamic birthday;@dynamic name;@dynamic details;@end

以及ContactDetailInfo.h文件

#import <Foundation/Foundation.h>#import <CoreData/CoreData.h>@class ContactInfo;@interface ContactDetailInfo : NSManagedObject@property (nonatomic, retain) NSString * address;@property (nonatomic, retain) NSString * name;@property (nonatomic, retain) NSString * telephone;@property (nonatomic, retain) ContactInfo *info;@end

和ContactDetailInfo.m文件

#import "ContactDetailInfo.h"#import "ContactInfo.h"@implementation ContactDetailInfo@dynamic address;@dynamic name;@dynamic telephone;@dynamic info;@end

此时,数据模型编辑器视图最右边栏中,实体的class就变成具体的类名

之前用Key-Value的代码就可以修改为:

#import "ContactInfo.h"#import "ContactDetailInfo.h"
- (void)insertCoreData{    NSManagedObjectContext *context = [self managedObjectContext];        ContactInfo *contactInfo = [NSEntityDescription insertNewObjectForEntityForName:@"ContactInfo" inManagedObjectContext:context];    contactInfo.name = @"name B";    contactInfo.birthday = @"birthday B";    contactInfo.age = @"age B";        ContactDetailInfo *contactDetailInfo = [NSEntityDescription insertNewObjectForEntityForName:@"ContactDetailInfo" inManagedObjectContext:context];    contactDetailInfo.address = @"address B";    contactDetailInfo.name = @"name B";    contactDetailInfo.telephone = @"telephone B";        contactDetailInfo.info = contactInfo;    contactInfo.details = contactDetailInfo;        NSError *error;    if(![context save:&error])    {        NSLog(@"不能保存:%@",[error localizedDescription]);    }}
- (void)dataFetchRequest{    NSManagedObjectContext *context = [self managedObjectContext];    NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];    NSEntityDescription *entity = [NSEntityDescription entityForName:@"ContactInfo" inManagedObjectContext:context];    [fetchRequest setEntity:entity];    NSError *error;    NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];    for (ContactInfo *info in fetchedObjects) {                NSLog(@"name:%@", info.name);        NSLog(@"age:%@", info.age);        NSLog(@"birthday:%@", info.birthday);        ContactDetailInfo *details = info.details;        NSLog(@"address:%@", details.address);         NSLog(@"telephone:%@", details.telephone);    }}

三、数据库相关

1.打印隐藏的sql语句:

在Edit Scheme中选择Run,之后进入Arguments标签,添加参数:“-com.apple.CoreData.SQLDebug 1”

2.使用SQLite存储时,数据库结构

存储的SQLite数据库表名称:大写“Z”加上实体名称大写,一个实体相当于一张表

具体的字段名称:大写“Z”加上实体属性名称大写

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 存折密码输错6次怎么办 营业执照原件丢失怎么办怎么注销 违章扣了14分怎么办 c1驾驶本过期了怎么办 考驾照没带身份证怎么办 上海扣满12分怎么办 美宝旅行证丢失怎么办 汽车证件全丢了怎么办 车的行驶本丢了怎么办 车和行驶证丢了怎么办 考驾照人在外地怎么办 外地考驾照没有居住证怎么办 考驾驶证预约密码忘了怎么办 考驾照密码忘了怎么办 考驾照的密码忘了怎么办 手机银行登录密码忘了怎么办 宽带账号或密码错误怎么办 车险过户联系不上原车主怎么办 换车了etc忘拆了怎么办 c1d驾驶证d证到期了怎么办 摩托车驾驶证过五年怎么办 没居住证想上东莞牌怎么办 外地考驾照需要暂住证怎么办 考驾照期间暂住证过期怎么办 b2驾照扣了6分怎么办 c1驾照扣了11分怎么办 c1驾驶证分扣9分怎么办 驾驶证c照扣6分怎么办 驾照过期1个月怎么办 上海驾驶证b证扣分怎么办 临时牌驾照丢了怎么办 行驶证年审过期两年怎么办 驾证到期了没换怎么办 在非洲被蚊子咬怎么办 身份证丢了被非法贷款怎么办 未满16岁怎么办身份证 放弃继承权后想反悔怎么办 上海居住证积分中社保断怎么办 换驾驶证但是身份证地址变动怎么办 驾驶证b证扣分了怎么办 c1驾证过期没审怎么办