您的位置:首页 > 移动开发 > IOS开发

[ios开发基础之CoreData[4]]CoreData深入分析篇

2012-09-24 23:57 435 查看
CoreData深入分析篇

本文来源:http://wangliang.me/?p=492

通过上一篇iPhone开发之SQLite的学习,基本学会了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

@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的实现方法会处理这些事情。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: