core data使用教程
从印象中记得还是在学校的时候老师讲过的时候用过,那时觉得好难,以至于工作2年多了一直没敢去看core data,前几天想了下,不去看不行,得都会用才行,于是那天6点下班后就准时回到了家里,然后一直看到晚上11点多,终于黄天不负有心人,把这块看完了。下面是一些用法:
为什么要用Core Data
CoreData的学习是需要一定成本的。以至于我认识的人很少在用,大家要不就是用一个FMDB。或者做的App是一个已有的Web的延伸,数据直接用Web端的Api取回来就好了。
我们要用Core Data的理由有以下几点:
Core Data是对底层存储的一次封装。封装了以后就变成ORM的框架。这样就变成操作对象。Core Data自己去进行数据的保存。
使用Core Data而不是FMDB,让整个程序架构更加的面向对象。
Core Data仅仅使用了Objective-C和Core Foundation,你不必去加入一些第三方的库。
Core Data是Apple的原生技术。每年的WWDC都能看到新特性的加入和讲授。
Core Data支持iCloud。而使用iCloud的App。Apple推荐的可能性增加。
有了iCloud为以后Apple的全平台数据共享打下基础
所以,没有理由拒绝使用Core Data做为你App的持久化。Core Data应该是一个跟Apple混的第一选择。
存储原理
NSManagedObjectModel
NSManagedObjectModel相当于一个数据库里面所有字段的实体类(或模型类)。
NSPersistentStoreCoordinator
NSPersistentStoreCoordinator是整个Core Data的核心。因为承担着全部数据的持久化,加载数据,缓存数据的工作。可以看做Core Data的心脏。
值得我们开心的事情是,虽然NSPersistentStoreCoordinator很重要,但是我们在写程序的时候其实只用初始化和设置一些很简单的参数就可以使用了。在我们App的整个生命周期里面其实并不会很频繁的使用到它。
初始化NSPersistentStoreCoordinator
初始化NSPersistentStoreCoordinator分为两个步骤
用已经初始化好的NSManagedObjectModel去初始化它
选择NSPersistentStore为存储的方式
NSPersistentStore
理论上来说NSPersistentStoreCoordinator的数据不一定要存到硬盘上,它可以存到内存里,可以存到网络上。不过都肯定是对应着不同的应用场景。所以我们一般情况还是把它存储到磁盘上。
接下来很重要的一句是
[_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]
第一个参数官方文档是这样写的:A string constant (such as NSSQLiteStoreType) that specifies the store type—see Store Types for possible values. 个人理解其实就是要存储数据类型。
第二个参数比较高级。我还没有用到过。文档上写的是设置为nil的时候是把NSPersistentStoreCoordinator作为默认的配置,如果是其他参数可能是把NSPersistentStoreCoordinator设置为其他的用途。此函数的第一个参数是指定NSPersistentStore的存储类型,我们之前说过的三种类型之一。NSSQLiteStoreType就代表这SQLite文件类型。
第三个参数就是我们要存储文件的位置。刚刚我们不是获得的沙箱里面的Document文件夹路经了么。然后我们把文件名加入拼为了一个文件的完整路经传入。
第四个参数类型是一个字典,我们可以传入不同的参数来指定这个NSPersistentStore的类型。比如在本地比如在iCloud。比较高级先为nil。
最后一个参数,为error,传入一个error指针。
NSManagedObjectContext
NSManagedObjectContext是我们很经常使用到的一个类。对于为什么要有这个类我个人理解是这样的,在我有限的数据库知识中记得,IO操作是很费时的,因此数据库一般情况是把一系列的操作缓存到了一个内存区域,等待合适的实际在去写入真实的磁盘中。这样大大的提高效率。如果你插入一条数据,然后修改数据,最后删除掉这条数据。如果是每次都执行Commit的话是操作三次IO,如果我们把这三条合并在一起commit的话。是任何事情都不必做。这样能有效的提高整个系统的效率。我认为NSManagedObjectContext的作用在于跟持久化直接做了这层缓存。我们使用Core Data。
还有一点需要注意的是NSManagedObjectContext并不是线程安全的。
关于NSManagedObjectContext的线程安全和高级解释,可以到网上查看。
初级应用的话只用记住一个就ok了NSManagedObjectContext是有一个NSManagedObjectContextConcurrencyType的属性。如果我们是UI操作(主线程操作)我们应该把它设置为NSMainQueueConcurrencyType类型的。
代码加载NSManagedObjectContext
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
NSPersistentStoreCoordinator从NSManagedObjectModel得到模型然后选择NSPersistentStore作为持久化目的地,然后NSManagedObjectContext在作为NSPersistentStoreCoordinator的一个缓存区给我们操作。
用法及步骤
1.创建iOS工程时勾选user data选项(其实不用这种方法也可以在项目里面自己写);
2.进入项目之后在AppDelegate.h和AppDelegate.m文件,xcode已经帮我们智能的创建好的需要的部分代码和一个coredatatest.xcdatamodeld实体文件;
AppDelegate.h中
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;
AppDelegate.m中
#pragma mark - Core Data stack
@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
- (NSURL *)applicationDocumentsDirectory {
// The directory the application uses to store the Core Data store file. This code uses a directory named "XY.coredatatest" in the application's documents directory.
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
- (NSManagedObjectModel *)managedObjectModel {
// The managed object model for the application. It is a fatal error for the application not to be able to find and load its model.
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"coredatatest" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
// The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it.
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
// Create the coordinator and store
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"coredatatest.sqlite"];
NSError *error = nil;
NSString *failureReason = @"There was an error creating or loading the application's saved data.";
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
// Report any error we got.
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[NSLocalizedDescriptionKey] = @"Failed to initialize the application's saved data";
dict[NSLocalizedFailureReasonErrorKey] = failureReason;
dict[NSUnderlyingErrorKey] = error;
error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict];
// Replace this with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return _persistentStoreCoordinator;
}
- (NSManagedObjectContext *)managedObjectContext {
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.)
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (!coordinator) {
return nil;
}
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
return _managedObjectContext;
}
#pragma mark - Core Data Saving support
- (void)saveContext {
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
NSError *error = nil;
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
}
3.实现“增删改查”
- 增加(插入)
- (void)insertData {
Person *newPerson = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:self.managedObjectContext];
if (newPerson != nil) {
newPerson.firstName = @"lisi";
newPerson.lastName = @"dada";
newPerson.age = @65;
NSError *savingError = nil;
if ([self.managedObjectContext save:&savingError]) {
NSLog(@"success");
} else {
NSLog(@"failed to save the context error = %@", savingError);
}
} else {
NSLog(@"failed to create the new person");
}
}
- 修改(更新)
- (void)updateData {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSError *requestError = nil;
NSArray *persons = [self.managedObjectContext executeFetchRequest:fetchRequest error:&requestError];
if ([persons count] > 0) {
Person *lastPerson = [persons lastObject];
lastPerson.firstName = @"zhangsan";
lastPerson.lastName = @"nihao";
lastPerson.age = @110;
NSError *savingError = nil;
if ([self.managedObjectContext save:&savingError]) {
NSLog(@"successfully saved the context");
} else {
NSLog(@"failed to save the context error = %@", savingError);
}
} else {
NSLog(@"could not find any person entity in the context");
}
}
- 查询(查找)
- (void)findData {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSPredicate *agePre = [NSPredicate predicateWithFormat:@"age < 50"];
[fetchRequest setPredicate:agePre];
NSError *requestError = nil;
NSArray *persons = [self.managedObjectContext executeFetchRequest:fetchRequest error:&requestError];
int counter = 0;
for (Person *thisPerson in persons) {
NSLog(@"person-->%d, firstName = %@, lastName = %@, age = %d", counter, thisPerson.firstName, thisPerson.lastName, [thisPerson.age intValue]);
counter++;
}
}
- 删除
- (void)deleteData {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSPredicate *agePre = [NSPredicate predicateWithFormat:@"age < 50"];
[fetchRequest setPredicate:agePre];
NSError *requestError = nil;
NSArray *persons = [self.managedObjectContext executeFetchRequest:fetchRequest error:&requestError];
for (Person *thisPerson in persons) {
NSLog(@"person-->firstName = %@, lastName = %@, age = %d", thisPerson.firstName, thisPerson.lastName, [thisPerson.age intValue]);
[self.managedObjectContext deleteObject:thisPerson];
NSError *savingError = nil;
if ([self.managedObjectContext save:&savingError]) {
NSLog(@"successfully saved the context");
} else {
NSLog(@"failed to save the context error = %@", savingError);
}
}
}
core data数据
我用的是SQLliteManager人家打开的数据库,查看:
Core Data 和 sqlite3的性能对比(网上找的)
原文地址:http://blog.csdn.net/hherima/article/details/9120253
这里我只把总结贴一下吧:
用后感受
用后觉得也挺简单的,没有想象的那么难,不用去自己写sql语句,但是和sqlite3还是有区别的,需要去取舍(哈哈哈)。