Core Data是iOS5之后才出现的一个框架,它提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite数据库文件中,也能够将保存在数据库中的数据还原成OC对象。
CoreData本质是一个ORM框架 ORM Objective-Relational Mapping 这个映射就是我们的模型文件,一般ORM框架都用XML格式来映射 实体Entity+属性数据库表
托管对象(entity) —既不是单纯 内存对象,也不是数据库中的具体的数据,它介于这两个状态之间的,我们叫他游离态的数据
CoreData 不能执行SQL语句 取而代之,操作的是对象, FMDB SQLite 可以直接SQL语句
在上图中,我们可以看到有五个相关模块:
1, Managed Object Model
Managed Object Model 是 述应用程序的数据模型,这个模型包含实体(Entity),特性(Property),读取请求(Fetch Request) 等。(下文都使用英文术语。)
2,Managed Object Context
Managed Object Context 参与对数据对象进行各种操作的全过程,并监测数据对象的变化,以 供对 undo/redo 的支持及更新绑定到数据的 UI。
3,Persistent Store Coordinator
Persistent Store Coordinator 相当于数据文件管理器,处理底层的对数据文件的读取与写入。一般我们无需与它打交道。
4,Managed Object
Managed Object 数据对象,与 Managed Object Context 相关联。
NSEntityDescription 常用方法:
+insertNewObjectForEntityForName:inManagedObjectContext: 工厂方法,根据给定的 Entity 述,生成相应的 NSManagedObject 对象,并插入 ManagedObjectContext 中。
-managedObjectClassName 返回映射到 Entity 的 NSManagedObject 类名
-attributesByName 以名字为 key, 返回 Entity 中对应的 Attributes
-relationshipsByName 以名字为 key, 返回 Entity 中对应的 Relationships
Property 为 Entity 的特性,它相当于数据库表中的一列,或者 XML 文件中的 value-key 对中的 key。它可以 述实体数据 (Attribute),Entity 之间的关系(RelationShip),或查询属性(Fetched Property)。
Attribute - NSAttributeDescription
Attribute 存储基本数据,如 NSString, NSNumber or NSDate 等。它可以有默认值,也可以使用正则表达式或其他条件对其值 进行限定。一个属性可以是 optional 的。Relationship - NSRelationshipDescription
Relationship 述 Entity,Property 之间的关系,可以是一对一,也可以是一对多的关系。Fetched Property - NSFetchedPropertyDescription
Fetched Property 根据查询谓词返回指定 Entity 的符合条件的数据对象。
Managed Object 表示数据文件中的一条记录,每一个 Managed Object 在内存中对应 Entity 的一个数据表示。Managed Object 的成员为 Entity 的 Property 所 述。
比如在上面的代码,person 这个 NSManagedObject,对应名为 Person 的 Entity。
每一个 Managed Object 都有一个全局 ID(类型为:NSManagedObjectID)。Managed Object 会附加到一个 Managed Object Context,我们可以通过这个全局 ID 在 Managed Object Context 查询对应的 Managed Object。
Managed Object Context 的作用相当重要,对数据对象进行的操作都与它有关。当创建一个数据对象并插入 Managed Object Context 中,Managed Object Context 就开始跟踪这个数据对象的一切变动,并在合适的时候 供对 undo/redo 的支持,或 调用 Persistent Store Coordinato 将变化保存到数据文件中去。
使用 Core Data document 类型的应用程序,通常会从磁盘上的数据文中中读取或存储数据,这写底层的读写就由 Persistent Store Coordinator 来处理。一般我们无需与它直接打交道来读写文件,Managed Object Context 在背后已经为我们调用 Persistent Store Coordinator 做了这部分工作。
Fetch Requests 相当于一个查询语句,你必须指定要查询的 Entity。我们通过 Fetch Requests 向 Managed Object Context 查询符合条件的数据对象,以 NSArray 形式返回查询结果,如果我们没有设置任何查询条件,则返回该 Entity 的所有数据对 象。我们可以使用谓词来设置查询条件,通常会将常用的 Fetch Requests 保存到 dictionary 以重复利用。
CoreDataManager.h
#import
#import
@interface CoreDataManager : NSObject
/**
* 管理对象的上下文---管理协调器
*/
@property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;
// 单例
+ (instancetype)sharedCoreDataManager;
@end
CoreDataManager.m
#import "CoreDataManager.h"
@implementation CoreDataManager
static CoreDataManager *manager;
#pragma mark - 创建coreDataManager单例
+ (instancetype)sharedCoreDataManager {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[self alloc] init];
});
return manager;
}
//// 沙盒路径
//- (NSURL *)applicationDocumentsDirectory {
// return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
//}
#pragma mark - 懒加载
- (NSManagedObjectContext *)managedObjectContext {
if (_managedObjectContext == nil) {
// 1.加载本地模型文件路径Person.xcdatamodeld
NSURL *url = [[NSBundle mainBundle] URLForResource:@"Person" withExtension:@"momd"];
// 2.创建管理对象模型 -- 需要模型文件(.xcdatamodeld)的URL路径 -- 手动添加模型文件
NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:url];
// 3.数据库沙盒中的路径URL
NSURL *storeURL = [[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject] URLByAppendingPathComponent:@"PersonCoreData.sqlite"];
// 4.创建协调器 -- 协调模型文件和数据库
NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
// 5.协调器中添加数据库
[coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:nil];
// 6.创建图形上下文----管理协调器
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
// 7.添加协调器
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
}
@end
Xcode 8.1已经不能直接找到
默认生成.swift文件
Xcode 8.1中,在使用Editor中的Create NSManagedObject Subclass 这个命令的时候,需要先把这个model的Codegen设置为Manual/None,否则会报错,在编译的时候。
设置之后可能还会报错
相互引用,删掉其中一个即可编译成功,这是Xcode的一个bug
#import "ViewController.h"
#import "CoreDataManager.h"
#import "Person+CoreDataClass.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self updata];
[self fetchRequestData];
}
#pragma mark - 写数据
- (void)updata {
// 通过实体来向数据库插入数据
// 通过Person.xcdatamodeld模型文件里添加的实体创建对象
Person *person = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:[CoreDataManager sharedCoreDataManager].managedObjectContext];
// 赋值
person.name = @"小明";
person.age = 18;
// 保存到数据库--上下文来保存
[[CoreDataManager sharedCoreDataManager].managedObjectContext save:nil];
}
#pragma mark - 通过fetch request发送请求读数据
- (void)fetchRequestData {
// 创建请求对象
/**
// 实体 - 从哪里的实体获取数据
@property (nullable, nonatomic, strong) NSEntityDescription *entity;
// 谓词 - 筛选条件 - 获取哪些数据
@property (nullable, nonatomic, strong) NSPredicate *predicate;
// 排序 升序还是降序
@property (nullable, nonatomic, strong) NSArray *sortDescriptors;
*/
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// 实体 - 从哪里的实体获取数据
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:[CoreDataManager sharedCoreDataManager].managedObjectContext];
fetchRequest.entity = entity;
// 谓词 - 筛选条件 - 获取哪些数据 (可选)
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name = %@",@"小明"];
fetchRequest.predicate = predicate;
// 排序 升序还是降序 - 数据库里可能有好几个叫小明的人 (可选) ascending:YES 升序
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:YES];
fetchRequest.sortDescriptors = @[sortDescriptor];
// 执行请求,获取数据
NSArray *PersonArr = [[CoreDataManager sharedCoreDataManager].managedObjectContext executeFetchRequest:fetchRequest error:nil];
for (Person *person in PersonArr) {
NSLog(@"%@----%lld",person.name,person.age);
}
}
@end
写入
读出
参考:深入浅出Cocoa教程