Core Data到底是个什么东西?是不是就是SQLite数据库?我觉得随着应用的越来越复杂,体现出来就是数据之间的关系越来越复杂,访问逻辑也变的更加的复杂臃肿,而相当多的应用都会用到数据的模型(或简单或复杂),所以苹果就单独弄了这样一个概念出现,并提供了辅助编辑/代码生成的工具,可以帮助减少不少工作量。至于说数据库,确实很多时候Core Data都是用数据库来做存储的支撑,但一来并非必须用数据库来存储,二来封装之后不需要任何SQL语句的,所以只能说数据库是支撑Core Data的技术之一,并非等价于Core Data。
Core Data里面自己定义了一些名词,什么NSManagedObject/NSManagedObjectContext/NSManagedObjectModel,这几个是最混淆的,其他的什么NSFetchRequest/NSEntityDescription还算好一点。(顺便吐槽一句,这种术语的翻译是最成问题的,不少书中还把这些翻成托管对象,托管对象上下文等等的,第一次看的时候你肯定一头雾水)
既然说到是Data,那么肯定是以数据为核心,同时封装对于数据的操作,形成一系列的辅助类。
NSManagedObject肯定是核心,这个可以看成一个一个的数据对象的实例,但封装后你很少直接访问这个类
NSManagedObjectContext是我们实际编程时打交道最多的,要访问一个数据对象,必须通过他的上下文
NSManagedObjectModel是我们整个应用程序里面的数据的抽象,包括了Entity,Attribute,Request等等
NSPresistentStoreCoordinator是对于数据存取的封装,封装了具体的加载/存储的实现细节
下面还是通过代码来看比较清晰,首先来看Xcode用于Core Data的辅助工具
编辑数据类型结束之后,Xcode会自动生成不少代码,其中每个Entity都会实现成一个类,Xcode会自动生成.h和.m文件
这个类实现的很简单,就是把属性列了一下,我们来看一下Event类的代码
- @interface Event : NSManagedObject
- @property (nonatomic, retain) NSDate * creationDate;
- @property (nonatomic, retain) NSNumber * latitude;
- @property (nonatomic, retain) NSNumber * longitude;
- @end
- <pre name="code" class="html">@implementation Event
- @dynamic creationDate;
- @dynamic latitude;
- @dynamic longitude;
- @end</pre>
除了这几个类之外,应用的Delegate也有巨大的改变,ManagedObjectModel/ManagedObjectContext都在这里生成。
- @property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
- @property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
- @property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
- - (void)saveContext;
- - (NSURL *)applicationDocumentsDirectory;
有了这些之后,我们来看数据的具体操作,假定我们要生成一个Event数据对象,并赋予当前的位置的值,然后存储起来
- Event *event = (Event*)[NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:self.managedObjectContext];
- CLLocationCoordinate2D coordinate = [_location coordinate];
- [event setCreationDate:[NSDate date]];
- [event setLatitude:[NSNumber numberWithDouble:coordinate.latitude]];
- [event setLongitude:[NSNumber numberWithDouble:coordinate.longitude]];
- NSError *error = nil;
- if (![self.managedObjectContext save:&error]) {
- NSLog(@"save new event error! errcode=%d", error.code);
- }
NSEntityDescription类是Entity的描述类,这个类有个全局的工厂方法,
+ (id)insertNewObjectForEntityForName:(NSString *)entityName inManagedObjectContext:(NSManagedObjectContext *)context;
这个方法会生成一个数据对象并添加到managedObjectContext里面。对于数据的存储,实用managedObjectContext的save方法,上面的代码生成了一个数据对象,加入了context,然后对数据对象进行了初始化,最后储存起来。
下面再看一段代码,这段代码用于查询所有的数据对象,并返回满足条件的对象数组
- NSFetchRequest *request = [[NSFetchRequest alloc] init];
- NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:self.managedObjectContext];
- [request setEntity:entity];
- NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"creationDate" ascending:NO];
- NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
- [request setSortDescriptors:sortDescriptors];
- [sortDescriptors release];
- [sortDescriptor release];
- NSError *error = nil;
- NSMutableArray *mutableFetchResults = [[self.managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
- if (mutableFetchResults) {
- self.eventArray = mutableFetchResults;
- [mutableFetchResults release];
- }
- [request release];
这也是非常常用的一个操作,这里先生成一个fetchRequest,然后告诉request在那个Entity里面查找,设置结束后运行managedObjectContext的executeFetchRequest方法,获得搜索到的所有对象(形成一个数组)
对数据对象的属性习惯上都是通过KVC来操作的,这里查询实用的是NSSortDescriptor,也可以使用NSPredicate这个类,使用fetchRequest的setPredicate方法设置一下即可。
对于数据的删除可以使用managedObjectContext的deleteObject方法,最后不要忘记调用save存储。
简单的数据操作差不多也就这几个内容了,增加,查询,删除,实现起来都很方便。
还有一个提一下,自动生成的数据对象的类(Event等等),里面是没有dealloc方法的,因为Core Data负责数据对象的整个生命周期,也就是说系统会自动的释放数据对象。