iPhone开发之CoreData(基础篇)
2012-08-16 19:20
495 查看
基本学会了SQLite在iPhone中的使用,这时候我就在找有没有SQLite的封装类,这样可以避免自己重复地SQLite的封装代码,Google一下,找到几个objc-sqlite、FMDB等,还有一些其它不知名的封装库,官方也提供了CoreData框架来提供完整的对象持久化存储方案,还是有必要要学习一下。
在CoreData有一些概念刚学习的时候不是很容易理解,还是要单独拿出来来梳理一下,这样学后面的内容不会感觉吃力。
图1
从图1中我们可以看到,在数据库结构中的一些术语,在这里会有对应,但不是全部。
♥ 表结构:NSEntityDescription
♥ 表记录:NSManagedObject
图2
从图2中我们可以看到一些数据库操作方面的一些术语
♥ 数据库存放方式:NSPersistentStoreCoordinator(持久化存储协调者)
♥ 数据库操作:NSManagedObjectContext(被管理的对象上下文)
还有一些类NSManagedObjectModel、NSFetchRequest什么的,具体项目就会有体会,下面来实战一下。
新建一个项目,项目模板基于“Master-Detail Application”,点击“Next”按钮,项目命名为“SimpleCoreData”,并勾选“Use Core Data”,点击“Next”,选择项目保存的目录,点击“Create”按钮,项目创建完毕。
图3
比以前创建的简单项目多了不少代码,还有xcdatamodeld文件,慢慢分析代码,AppDelegate.h头文件中,添加了三个property
再分析AppDelegate.m文件,有对应的三个方法来返回各自对应的对象
这些对象在哪里被调用的呢,打开MasterViewController.m,在初始化函数中,我们看到通过获取delegate,再通过delegate调用方法managedObjectContext,这样就得到了这个NSManagedObjectContext对象,NSManagedObjectContext对象它会跟NSPersistentStoreCoordinator对象打交道,NSPersistentStoreCoordinator会去处理底层的存储方式。
分析MasterViewController.m的代码发现以下函数的调用顺序。
♥ -tableView:(UITableView *)tableView cellForRowAtIndexPath:
♥ -configureCell:atIndexPath:
♥ -fetchedResultsController
最后是从fetchedResultsController获取到查询结果,那就有必要来分析一下
因为我们设置了aFetchedResultsController的委托NSFetchedResultsControllerDelegate,就要实现它的方法,幸运的是这些方法看起来都像下面这样,直接复制粘贴就行了。
这个删除对象为什么没有处理TableView的代码,因为我们实现NSFetchedResultsControllerDelegate委托,当对象上下文发生变化时NSFetchedResultsControllerDelegate的实现方法会处理这些事情。
基本概念
在CoreData有一些概念刚学习的时候不是很容易理解,还是要单独拿出来来梳理一下,这样学后面的内容不会感觉吃力。图1
从图1中我们可以看到,在数据库结构中的一些术语,在这里会有对应,但不是全部。
♥ 表结构:NSEntityDescription
♥ 表记录:NSManagedObject
图2
从图2中我们可以看到一些数据库操作方面的一些术语
♥ 数据库存放方式:NSPersistentStoreCoordinator(持久化存储协调者)
♥ 数据库操作:NSManagedObjectContext(被管理的对象上下文)
还有一些类NSManagedObjectModel、NSFetchRequest什么的,具体项目就会有体会,下面来实战一下。
新建一个项目,项目模板基于“Master-Detail Application”,点击“Next”按钮,项目命名为“SimpleCoreData”,并勾选“Use Core Data”,点击“Next”,选择项目保存的目录,点击“Create”按钮,项目创建完毕。
图3
代码分析
比以前创建的简单项目多了不少代码,还有xcdatamodeld文件,慢慢分析代码,AppDelegate.h头文件中,添加了三个property@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext; @property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel; @property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
再分析AppDelegate.m文件,有对应的三个方法来返回各自对应的对象
#pragma mark - Core Data stack - (NSManagedObjectContext *)managedObjectContext { ... return __managedObjectContext; } - (NSManagedObjectModel *)managedObjectModel { ... return __managedObjectModel; } - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { ... return __persistentStoreCoordinator; }
这些对象在哪里被调用的呢,打开MasterViewController.m,在初始化函数中,我们看到通过获取delegate,再通过delegate调用方法managedObjectContext,这样就得到了这个NSManagedObjectContext对象,NSManagedObjectContext对象它会跟NSPersistentStoreCoordinator对象打交道,NSPersistentStoreCoordinator会去处理底层的存储方式。
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.title = NSLocalizedString(@"Master", @"Master"); id delegate = [[UIApplication sharedApplication] delegate]; self.managedObjectContext = [delegate managedObjectContext]; } return self; }
查询实体
分析MasterViewController.m的代码发现以下函数的调用顺序。♥ -tableView:(UITableView *)tableView cellForRowAtIndexPath:
♥ -configureCell:atIndexPath:
♥ -fetchedResultsController
最后是从fetchedResultsController获取到查询结果,那就有必要来分析一下
- (NSFetchedResultsController *)fetchedResultsController { // 如果查询结果已经存在就直接返回__fetchedResultsController if (__fetchedResultsController != nil) { return __fetchedResultsController; } // 1.创建NSFetchRequest对象(相当于SQL语句) NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; // 2.创建查询实体(相当于设置查询哪个表) NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:self.managedObjectContext]; [fetchRequest setEntity:entity]; // 设置获取数据的批数. [fetchRequest setFetchBatchSize:20]; // 3.创建排序描述符,(ascending:是否升序) NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timeStamp" ascending:NO]; NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; [fetchRequest setSortDescriptors:sortDescriptors]; // 根据fetchRequest和managedObjectContext来创建aFetchedResultsController对象,并设置缓存名字为"Master". NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Master"]; // 设置aFetchedResultsController的委托对象为当前类 aFetchedResultsController.delegate = self; self.fetchedResultsController = aFetchedResultsController; NSError *error = nil; // 获取第一批数据 if (![self.fetchedResultsController performFetch:&error]) { // 错误处理 NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } return __fetchedResultsController; }
因为我们设置了aFetchedResultsController的委托NSFetchedResultsControllerDelegate,就要实现它的方法,幸运的是这些方法看起来都像下面这样,直接复制粘贴就行了。
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { [self.tableView beginUpdates]; } - (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type { switch(type) { case NSFetchedResultsChangeInsert: [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeDelete: [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; break; } } - (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { UITableView *tableView = self.tableView; switch(type) { case NSFetchedResultsChangeInsert: [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeDelete: [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeUpdate: [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; break; case NSFetchedResultsChangeMove: [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade]; break; } } - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { [self.tableView endUpdates]; }
添加实体
- (void)insertNewObject { // 从NSFetchedResultsController中获取NSManagedObjectContext对象 NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext]; // 从NSFetchedResultsController中获取实体描述 NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity]; // 在被管理上下文中插入一个新的NSManagedObject NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context]; // 字段赋值 [newManagedObject setValue:[NSDate date] forKey:@"timeStamp"]; // 保存被管理对象上下文,这样刚才的newManagedObject就被保存了 NSError *error = nil; if (![context save:&error]) { // 错误处理. NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } }
删除实体
// 从NSFetchedResultsController中获取NSManagedObjectContext对象 NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext]; // 从被管理对象上下文中删除MO对象 [context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]]; // 保存被管理对象上下文 NSError *error = nil; if (![context save:&error]) { // 错误处理 NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); }
这个删除对象为什么没有处理TableView的代码,因为我们实现NSFetchedResultsControllerDelegate委托,当对象上下文发生变化时NSFetchedResultsControllerDelegate的实现方法会处理这些事情。
相关文章推荐
- iPhone开发之CoreData(基础篇)
- iPhone开发之CoreData(基础篇)
- iphone开发之数据库CoreData
- iphone开发之数据库CoreData
- iPhone开发教程之Core Data 常见问题的总结
- iPhone开发之CoreData(实战篇)
- iphone开发 IOS中CoreData的通用代码
- iphone开发中数据存储 属性列表,归档,SQLite3,core data 还有FMDB应该选择哪种?
- iphone开发之数据库CoreData
- iPhone开发之CoreData(实战篇)
- 仿微信/QQ 开发基于XMPP的iPhone/iOS聊天客户端(三)CoreData
- iPhone开发之CoreData(实战篇)
- iphone开发之数据库CoreData
- iPhone开发之CoreData之 NSFetchedResultsController的使用
- iPhone/iOS Core Animation开发总结(CALayer)
- 深入理解iPhone数据持久化(手把手教你iphone开发 - 基础篇)
- IOS开发--CoreData 入门
- iOS 开发系列:CoreData Object 变成 Fault 的一种方式
- objective-c - 基础篇 - 数据库网络 -- Core Data数据库持久化
- iOS应用开发视频教程笔记(十四)Core Data Demo