iphone数据存储之-- Core Data的使用(一)

来源:互联网 发布:hbo直播软件 编辑:程序博客网 时间:2024/04/19 15:38

一、概念

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”加上实体属性名称大写


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 20个月宝宝大便间隔三天怎么办 两个多月的宝宝四天没大便怎么办 两个多月的宝宝几天没大便怎么办 2个月3天没大便怎么办 两个月大的宝宝发烧40度怎么办 两个月大的宝宝感冒了怎么办 四个月宝宝拉水样大便要怎么办 六个月的宝宝咳嗽有痰怎么办 未满月的宝宝大便脓状怎么办 五个月的宝宝总是吃手怎么办 小孩子学数字怎么也学不会怎么办 小孩学数字老是学不会该怎么办 只买了大人票忘买儿童的了怎么办 铝合金滑动门没轨道安纱门怎么办 移门衣柜门与柜体有冶缝隙怎么办 推拉门关门时撞门框声音大怎么办 两岁宝宝夏天不盖被子怎么办 家里有好多会爬的小黑虫怎么办 刚贴的壁纸怎么发霉了怎么办 晚上睡觉一熄灯有许多小虫子怎么办 一岁宝宝夏天爱哭不爱吃饭怎么办 合肥房子卖了户口没地方迁怎么办 忌作灶的日子新房装橱柜了怎么办 刮水泥浆的墙面刮不住腻子怎么办 小学二年级孩子偷钱 老师怎么办 发现自己读初中的儿子偷钱怎么办? 做错事了得不到亲人的原谅怎么办? 窗口 窗套与墙缝隙大怎么办 中班小孩还不会认1到10怎么办 母猫奶头被小猫咬伤了怎么办 口红不小心弄到衣服上怎么办 脖子后背疼的睡不着觉应该怎么办 君子兰用高锰酸钾泡浓度高了怎么办 五个月宝宝认人不要奶奶睡怎么办 幼儿小班安全卡鱼刺了怎么办教案 学籍在一年级学生在二年级怎么办 一岁多宝宝挑食不爱吃饭菜怎么办饭 换了新手机微信好友显示不全怎么办 朋友人在外地 联系不上怎么办 幼儿连字母都记不住该怎么办 车一边轮子掉农村路边小水沟怎么办