iOS学习笔记——Core Data

本地存储是个很重要的模块,几乎所有应用都会用到,Apple的Core Data是和UIKit相同等级的技术机制,可见对其的重视,这篇博文对iOS的Core Data机制做个初步学习总结。

首先和Android上的机制做一下对比,iOS和Android一样使用SQLite数据库用作本地数据保存,两个平台也都对数据库操作做了封装:

Android:覆写SQLiteOpenHelper类进行数据库创建、更新等数据库层面的操作;使用SQLiteDatabase对象调用封装好的方法对数据库进行CRUD;使用ContentValue对象进行数据传递。实际开发中,为了增加效率,也会使用类似FinalDb之类的数据库快速开发库。

iOS:使用Core Data机制进行本地存储。和Android相比,CD机制更加抽象,在设计时通过Xcode进行可视化建模;在使用时通过CD机制,不需要接触SQL。使用NSManagedObject对象描述Entity,使用NSManagedObjectContext对象进行方便的CRUD操作。Core Data通过NSPersistentStoreCoordinator连接上层操作和底层存储。

下面从Core Data架构NSManagedObjectContext获取CRUD三个方面分别描述。

Core Data 架构

在业务逻辑中使用Core Data 时,只接触NSManagedObject和NSManagedObjectContext类。但是在获取NSManagedObjectContext时,可以看到Core Data实际有几层的抽象结构,来保证稳定性和可扩展性。

Architecture

 

上图中左侧的四个类构成了逻辑上的结构,上层是NSManagedObjectContext类,这是业务逻辑中操作数据的主要入口。底层是NSPersistentStore类,Store对应本地实际存储的文件,因为有Store这层的抽象,可以将再底层的文件系统根据需求进行修改,比如远端文件系统,同时保证上层逻辑不需要修改。中间的NSPersistentStoreCoordinator是上层和底层之间的协调者,在一个应用中,上层可以有多个Context,下层可能对应多个Store,Coordinator对其进行协调。

没有提到的NSManagedModel,是对模型结构的描述,记录模型信息,使用Model中的信息创建合适、对应设计的数据库文件。

右侧的目录说明了本地数据文件和Data Model文件所在的位置。Data Model文件对应Xcode中创建的Data Model文件,扩展名“.xcdatamodeld”,也是在这个文件中进行可视化数据建模。在.app包中,Data Model的扩展名是“.momd”。

Document目录下的,就是Store对应的本地实际存储数据的数据库文件。

获取数据库文件路径:

NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreDataBooks.CDBStore"];
获取Data Model文件路径:
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"CoreDataBooks" withExtension:@"momd"];

获取关联的NSManagedObjectContext

按照上图的蓝色箭头,获取NSManagedObjectContext需要下面三个对象。

1. 创建NSManagedModel:(modelURL参见上文)

[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
2\. 创建NSPersistentStoreCoordinator:
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]]
3\. 创建NSPersistentStore并关联NSPersistentStoreCoordinator:(storeURL参见上文)
[_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]
准备工作做好之后即可创建并关联NSManagedObjectContext: 4\. 获取关联的NSManagedObjectContext:
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator: [self persistentStoreCoordinator]]
上面的步骤就是获取关联Context的步骤,Apple官方的实例中,包含了标准步骤的代码。 ### **使用NSManagedObjectContext进行CRUD** Core Data对每条数据进行了封装,使用NSManagedObject的子类表示数据。Xcode可以自动生成NSManagedObject的子类。 [![屏幕快照 2014-10-14 下午4.26.24](https://static.kyleduo.com/2014/10/屏幕快照-2014-10-14-下午4.26.24-300x196.png)](https://static.kyleduo.com/2014/10/屏幕快照-2014-10-14-下午4.26.24.png) 插入数据: 插入数据时通过NSEntityDescription类向NSManagedObjectContext中插入一个对象,对对象进行赋值操作之后,使用NSManagedObjectContext的save方法进行提交。
TestEntity *entityToAdd = [NSEntityDescription insertNewObjectForEntityForName:@"TestEntity"
     inManagedObjectContext:self.context];
entityToAdd.name = @"name";
BOOL result = [self.context save:Nil];
事实上修改数据包含在了插入数据中,也就是赋值并提交。 查询数据: Core Data查询数据使用NSFetchRequest类。这个类封装了一次查询请求,使用NSPredicate类限制查询条件,使用NSSortDescriptor类对结果进行排序。
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"TestEntity"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == 'name'"];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"date" ascending:TRUE];
[request setPredicate:predicate];
[request setSortDescriptors:@[sortDescriptor]];
self.data = [[self.context executeFetchRequest:request error:Nil] mutableCopy];
删除数据:
[self.context deleteObject:self.data[i]];