CoreData入门简介
CoreData 是 iOS3.0 时引入的一个数据持久化的框架。他与 sqlite 对比最大的优点莫过于支持对象的存储了,苹果的官方文档说其简化了数据库的操作(个人用起来感觉依然没有 FMDB 简单),使用 CoreData 确实可以大量减少代码中的 SQL 语句。
先来介绍一下 CoreData 里面一些基础性的东西吧:
Core Data 基本结构
NSPersistentStoreCoordinator
NSPersistentStoreCoordinator是一个位于本地存储文件与缓存层(NSManagedObjectContext)之间的一个持久化层,他是真实操作数据库本地文件。
其初始化主要为两个步骤:
- 用已经初始化好的NSManagedObjectModel去初始化它
- 选择NSPersistentStore为存储的方式
- (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;
}
NSPersistentStoreCoordinator的数据存储形式目前支持三种:SQLite、二进制、XML
NSManagedObjectContext
NSManagedObjectContext是一个被管理数据的上下文,他实际上是对你所有数据库操作的一个缓存层,把你所有的操作都先缓存起来避免大量磁盘 IO 造成不流畅,你在操作完数据库后调用其save方法,就可以把你的数据库操作提交给持久化层(NSPersistentStoreCoordinator),由持久化层一次性写入数据库文件。初始化:
- (NSManagedObjectContext *)managedObjectContext{
if (__managedObjectContext != nil) {
return __managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
__managedObjectContext = [[NSManagedObjectContext alloc] init];
[__managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return __managedObjectContext;
}
NSManagedObjectModel
NSManagedObjectModel可以把它看做为一个 Core Data 的 schema。生成这个类的来源就是在 xCode 里的.xcdatamodeld文件,我们可以可视化的对这个文件进行操作,实际上这个文件也就相当于数据库的 schema,这个文件编译后就是.momd或.mom文件。我们可以根据这个初始化NSManagedObjectModel:
- (NSManagedObjectModel *)managedObjectModel{
if (__managedObjectModel != nil) {
return __managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"TestApp" withExtension:@"momd"];
__managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return __managedObjectModel;
}
NSManagedObject
NSManagedObject是被管理的数据记录。对应着就是数据库的一个表,在我们适用 xCode 编辑完数据库的表结构之后可以通过xCode->Editor->Create NSManagedObject Subclass...来创建对应表的 model
NSFetchRequest
NSFetchRequest就相当于是 SQL 里面的查询语句,我们使用它替代了 sql 语句。这个支持谓词查询
NSEntityDescription
NSEntityDescription相当于表结构。里面包含Attributes、Relationships、Fetched Properties三部分内容。也就是你在编辑.ecdatamodeld右边的三组内容
参考
Core Data 多线程
简介
在应用中设计数据量大的时候必然要通过子线程来进行数据库相关操作,这就涉及到线程安全问题了。其多线程下的使用这里有三中方案:
须知道,CoreData的NSPersistentStoreCoordinator和NSManagedObjectContext对象都是不能跨线程使用的,我们注意到:
- (id)initWithConcurrencyType:(NSManagedObjectContextConcurrencyType)ct
NSManagedObjectContextConcurrencyType 一共有三种:
- NSConfinementConcurrencyType
- NSPrivateQueueConcurrencyType
- NSMainQueueConcurrencyType
NSPrivateQueueConcurrencyType与NSMainQueueConcurrencyType分别对应绑定一个后台线程与主线程。可以使用performBlock:开执行原来需要使用dispatch_async封装的代码.
NSConfinementConcurrencyType不能执行performBlock:
NSManagedObjectContext是可以基于其他的NSManagedObjectContext的,通过setParentContext方法,可以设置另外一个NSManagedObjectContext为自己的父级,这个时候子级可以访问父级下所有的对象,而且子级NSManagedObjectContext的内容变化后,如果执行 save 方法,会自动的 merge 到父级NSManagedObjectContext中,也就是子级 save 后,变动会同步到父级NSManagedObjectContext。当然这个时候父级也必须再 save 一次,如果父级没有父级了,那么就会直接向NSPersistentStoreCoordinator中写入,如果有就会接着向再上一层的父级冒泡...
通过三个级别的NSManagedObjectContext, 一个负责在 background 更新NSPersistentStoreCoordinator。一个用在主线程,主要执行插入,修改和删除操作,一些小的查询也可以在这里同步执行,如果有大的查询,就起一个新的NSPrivateQueueConcurrencyType类型的NSManagedObjectContext,然后放在后台去执行查询,查询完成后将结果返回主线程。
实际上这种多线程的访问也类似 FMDB 中FMDatabaseQueue,就是把数据库操作全部放到一个子线程中,然后所有的操作都最终调用这个子线程来执行
参考:
通则不痛,远离阻塞-在多线程环境中使用CoreData,以及一个简单的封装
CoreData 多线程下NSManagedObjectContext的使用
代码参考
Core Data是如何保存的
- 当然是NSManagedObjectContext调用save方法的时候。
- 这时候context里面持有的那些NSManagedObject将会自己调用自己的willSave方法。
- NSManagedObjectContextWillSaveNotification发出。
- 开始验证。这个验证可能是你在data model里面写的。也可以是在NSManagedObject里面代码写的。
- 验证结束以后数据就合并到NSPersistentStoreCoordinator和NSPersistentStore里面。
- 如果你在合并的时候更改了数据。这时候会重新验证数据。
- 这个时候已经把需要验证过的合并数据存到持久化介质当中。
- 最后NSManagedObjectContextDidSaveNotification这个通知发出。