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文件中,自动生成

1
2
3
4
5
6
@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文件中,自动生成

1
2
3
@synthesize managedObjectContext = __managedObjectContext;
@synthesize managedObjectModel = __managedObjectModel;
@synthesize persistentStoreCoordinator = __persistentStoreCoordinator;

保存数据到持久层

1
2
3
4
- (void)applicationWillTerminate:(UIApplication *)application
{
    [self saveContext];
}
1
2
3
4
5
6
7
8
9
10
11
- (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目录路径

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

被管理的数据上下文

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

1
2
3
4
5
6
7
8
9
10
11
12
- (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文件编译而来

1
2
3
4
5
6
7
8
9
- (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目录下,以及数据库名称

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- (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头文件

1
#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插入数据,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
- (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来查询插入的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- (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文件

1
2
3
4
5
6
7
8
9
10
11
12
13
#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框架为此类属性生成存取方法

1
2
3
4
5
6
7
8
9
10
11
12
#import "ContactInfo.h"
#import "ContactDetailInfo.h"
 
 
@implementation ContactInfo
 
@dynamic age;
@dynamic birthday;
@dynamic name;
@dynamic details;
 
@end

以及ContactDetailInfo.h文件

1
2
3
4
5
6
7
8
9
10
11
12
13
#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文件

1
2
3
4
5
6
7
8
9
10
11
12
#import "ContactDetailInfo.h"
#import "ContactInfo.h"
 
 
@implementation ContactDetailInfo
 
@dynamic address;
@dynamic name;
@dynamic telephone;
@dynamic info;
 
@end

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

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

1
2
#import "ContactInfo.h"
#import "ContactDetailInfo.h"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
- (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]);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- (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”加上实体属性名称大写

Core Data (2)-备用的更多相关文章

  1. Core Data-备用

    Core Data是一个功能强大的层,位于SQLite数据库之上,它避免了SQL的复杂性,能让我们以更自然的方式与数据库进行交互.Core Data将数据库行转换为OC对象(托管对象)来实现,这样无需 ...

  2. iOS数据持久化 -- Core Data-备用

    Core Data是一个功能强大的层,位于SQLite数据库之上,它避免了SQL的复杂性,能让我们以更自然的方式与数据库进行交互.Core Data将数据库行转换为OC对象(托管对象)来实现,这样无需 ...

  3. Core Data入门-备用

    简介 Core Data是iOS5之后才出现的一个框架,它提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite数据库文件中,也能够将保存在数据库中的数据还原成OC对象. ...

  4. Core Data数据持久性存储基础教程-备用

    摘要 就像我一直说的,Core Data是iOS编程,乃至Mac编程中使用持久性数据存储的最佳方式,本质上来说,Core Data使用的就是SQLite,但是通过一系列特性避免了使用SQL的一些列的麻 ...

  5. iOS之Core Data及其线程安全

    一.简介 Core Data是iOS5之后才出现的一个框架,它提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite数据库文件中,也能够将保存在数据库中的数据还原成OC对 ...

  6. Core Data的一些常见用法

    一.简介 Core Data是一个纯粹的面向对象框架,其本质就是一个ORM(对象关系映射:Object Relational Mapping),能以面向对象的方式操作SQLite数据库.在实际开发中绝 ...

  7. Core Data 使用映射模型

    Core Data 使用映射模型 如果新版本的模型存在较复杂的更改,可以创建一个映射模型,通过该模型指定源模型如何映射到目标模型. 创建映射模型,新建File,  Core Data 选择Mappin ...

  8. SELF, self in CORE DATA

    Predicate SELF Represents the object being evaluated. CORE DATA Retrieving Specific Objects If your ...

  9. Core Data浅谈初级入门

    Core Data是iOS5之后才出现的一个框架,它提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite数据库文件中,也能够将保存在数据库中的数据还原成OC对象.在此数 ...

随机推荐

  1. Lintcode--001(比较字符串)

    比较两个字符串A和B,确定A中是否包含B中所有的字符.字符串A和B中的字符都是 大写字母 注意事项 在 A 中出现的 B 字符串里的字符不需要连续或者有序. 您在真实的面试中是否遇到过这个题? Yes ...

  2. 这样就算会了PHP么?-7

    循环之类的例子 <script language="javascript"> function calculate(a, b) { return a * b; } do ...

  3. Row Cache Objects

    This latch comes into play when user processes are attempting to access or update the cached data di ...

  4. intel安装mac os

    一.变色龙: 1.http://bbs.pcbeta.com/forum.php?mod=viewthread&tid=1518901&extra=page%3D1%26orderby ...

  5. DHTML【8】--CSS

    在讲HTML时说过,有个Style标签是在CSS里用的,是的,在HTML中添加CSS样式必须要用到Style,在标签里单独定义标签属性时用的是Style属性.上一节我们也说过,先不用管那个Style标 ...

  6. PHP常用魔术方法(__invoke魔术方法)

    <?php //文件名:index.php define('a',__DIR__); include '/IMooc/Loader.php'; spl_autoload_register('\\ ...

  7. PHP常用魔术方法(__call魔术方法:)

    魔术方法  __call <?php //文件名:index.php define('a',__DIR__); include '/IMooc/Loader.php'; spl_autoload ...

  8. Android——ViewPager多页面滑动切换以及动画效果

    一.首先,我们来看一下效果图,这是新浪微博的Tab滑动效果.我们可以手势滑动,也可以点击上面的头标进行切换.与此同方式,白色横条会移动到相应的页卡头标下.这是一个动画效果,白条是缓慢滑动过去的.好了, ...

  9. 基于PCA和SVM的人脸识别

    程序中采用的数据集是ORL人脸库,该人脸库共有400副人脸图像,40人,每人10幅,大小为112*92像素,同一个人的表情,姿势有少许变化. 程序的流程主要分为三部分,数据的预处理(PCA降维和规格化 ...

  10. 第27讲 UI组件之 ScrollView与底部动态添加数据

    第27讲 UI组件之 ScrollView与底部动态添加数据 1. ScrollView(滚动视图) ScrollView(滚动视图)是实现滚动的一个控件,只需要将需要滚动的控件添加到ScrollVi ...