CoreData学习笔记(二)
来源:互联网 发布:centos 下安装broadcom 编辑:程序博客网 时间:2024/05/16 11:27
这篇文章重点讲讲CoreData的Fetched Results Controller。
对应的objc类为NSFetchedResultsController。这个类是用来管理CoreData Fetch request返回的对象的。
在创建这个控制器之前,必须先创建fetch request。 fetch request描述了详细的查询规则,还可以添加查询结果的排序描述(sort descriptor)。fetchResultsController根据已经创建完的fetch request来创建, 它是NSFetchedResultsController的实例,这个实例的主要任务就是使用fetch request来保证它所关联的数据的新鲜性。创建了fetchResultsController实例后要做一下初始化,一般初始化是向这个控制器发送PerformFetch消息,下面是这一过程的代码。
- (NSFetchedResultsController *)fetchedResultsController { if (fetchedResultsController != nil) { return fetchedResultsController; } /* Set up the fetched results controller. */ // Create the fetch request for the entity. NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; // Edit the entity name as appropriate. NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:managedObjectContext]; [fetchRequest setEntity:entity]; // Set the batch size to a suitable number. [fetchRequest setFetchBatchSize:20]; // Edit the sort key as appropriate. NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timeStamp" ascending:NO]; NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor,nil]; [fetchRequest setSortDescriptors:sortDescriptors]; // Edit the section name key path and cache name if appropriate. // nil for section name key path means "no sections". NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:@"Root"]; aFetchedResultsController.delegate = self; self.fetchedResultsController = aFetchedResultsController; [aFetchedResultsController release]; [fetchRequest release]; [sortDescriptor release]; [sortDescriptors release]; return fetchedResultsController; }
`这个函数用来创建FetchedResultsController,过程还是比较简单的,下面是初始化这个控制器代码。
NSError *error = nil; if(![[self fetchedResultsController]performFetch: &error]){ //handle the error appropriately NSLog(@"Unresolved error %@, %@", error, [error userInfo]); exit(-1); }
这段代码一般会放在viewDidLoad函数中,初始化之后,fetchedResultsController就与数据相连接了,之后要取数据都能直接从这个控制器提供的方法中去取。
实现这个控制器,最关键的还要实现Fetched Results Controller Delegate Methods。控制器与数据源连接后,控制器监视器会时刻监视着数据源,当数据源发生
改变后,监视器会调用对应的协议方法,改协议总共要实现四个方法,分别为:
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller; - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller; - (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath; - (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type;
下面依次来解释这四个协议方法。
1. - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
当控制器监控的数据发生改变时,如对象被删除,有插入,更新等,监视器会在数据发生改变前意识到这个情况,此时就会调用这个函数。往往我们用列表的形式
表现数据,此时意味着屏幕上的数据即将过时,因为数据马上要改变了,这是这个协议方法的工作就是通知列表数据马上要更新的消息,往往代码是这样实现的。- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { [self.tableView beginUpdates]; }
2. - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
当fetchedResultsController完成对数据的改变时,监视器会调用这个协议方法。在上面提到的情况,这个方法要通知列表数据已经完成,可以更新显示的数据这个
消息,因此通常的实现是这样的。- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { [self.tableView endUpdates]; }
3. - (void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
当fetchedResultsController发现指定的对象有改变时,监视器会调用这个协议方法。这里改变的类型从列表中体现有 更新、插入、删除或者行的移动。因此这个
方法要实现所有的这些方法,以应对任何一种改变。下面是这个方法的标准实现。
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { switch(type) { case NSFetchedResultsChangeInsert: [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeDelete: [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeUpdate: { NSString *sectionKeyPath = [controller sectionNameKeyPath]; if (sectionKeyPath == nil) break; NSManagedObject *changedObject = [controller objectAtIndexPath:indexPath]; NSArray *keyParts = [sectionKeyPath componentsSeparatedByString:@"."]; id currentKeyValue = [changedObject valueForKeyPath:sectionKeyPath]; for (int i = 0; i < [keyParts count] - 1; i++) { NSString *onePart = [keyParts objectAtIndex:i]; changedObject = [changedObject valueForKey:onePart]; } sectionKeyPath = [keyParts lastObject]; NSDictionary *committedValues = [changedObject committedValuesForKeys:nil]; if ([[committedValues valueForKeyPath:sectionKeyPath]isEqual:currentKeyValue]) break; NSUInteger tableSectionCount = [self.tableView numberOfSections]; NSUInteger frcSectionCount = [[controller sections] count]; if (tableSectionCount != frcSectionCount) { // Need to insert a section NSArray *sections = controller.sections; NSInteger newSectionLocation = -1; for (id oneSection in sections) { NSString *sectionName = [oneSection name]; if ([currentKeyValue isEqual:sectionName]) { newSectionLocation = [sections indexOfObject:oneSection]; break; } } if (newSectionLocation == -1) return; // uh oh if (!((newSectionLocation == 0) && (tableSectionCount == 1) && ([self.tableView numberOfRowsInSection:0] == 0))) [self.tableView insertSections:[NSIndexSet indexSetWithIndex:newSectionLocation] withRowAnimation:UITableViewRowAnimationFade]; NSUInteger indices[2] = {newSectionLocation, 0}; newIndexPath = [[[NSIndexPath alloc] initWithIndexes:indiceslength:2] autorelease]; } } case NSFetchedResultsChangeMove if (newIndexPath != nil) { [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; [self.tableView insertRowsAtIndexPaths: [NSArray arrayWithObject:newIndexPath] withRowAnimation: UITableViewRowAnimationRight]; } else { [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:[indexPath section]]withRowAnimation:UITableViewRowAnimationFade]; } break; default: break; } }
4. - (void)controller:(NSFetchedResultsController *)controller
didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex
forChangeType:(NSFetchedResultsChangeType)type
当改变控制器管理的对象后引起了列表section的变化,此时监视器就会调用这个协议函数。
下面是标准实现。- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type { switch(type) { case NSFetchedResultsChangeInsert: if (!((sectionIndex == 0) && ([self.tableView numberOfSections] == 1) && ([self.tableView numberOfRowsInSection:0] == 0))) [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeDelete: if (!((sectionIndex == 0) && ([self.tableView numberOfSections] == 1) && ([self.tableView numberOfRowsInSection:0] == 0))) [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeMove: case NSFetchedResultsChangeUpdate: default: break; } }
- CoreData学习笔记(二)
- CoreData学习笔记(二)
- CoreData 学习(二)
- CoreData学习笔记(始)
- CoreData学习笔记(一)
- CoreData学习笔记(一)
- CoreData学习笔记(始)
- IOS学习高级课程(二)coredata
- coredata学习总结(二)
- CoreData学习笔记
- CoreData学习笔记
- CoreData学习笔记
- CoreData学习笔记
- 学习CoreData框架笔记
- iOS学习笔记 CoreData
- 《CoreData》系列(二)
- CoreData 学习(一)
- IOS CoreData 使用(二)
- 电源的源效应和负载效应
- winform 调用生成按钮的事件(举一反三适用其他)
- 正确认识android内存管理原理
- DataSet与DataAdapter
- 【转】sscanf 函数(格式控制)详解
- CoreData学习笔记(二)
- 关于android xml文件中 android:id="@+id/my_button"的含义疑问
- 代码风格(二)函数
- 从UI设计上,“勾引”用户设置高强度的密码
- 学习嵌入式系统开发的经典网站
- Qt系列软件包 (搞不清Qtopia Core,Qt Extended,Qt-embedded.....的过来看看)
- winform窗口打开后文本框的默认焦点设置
- mark
- linux系统调用 和 库可函数调用