NSFetchedResultsController,才深深的体会到coredata的牛逼之处。原来Apple公司弄个新技术,不是平白无故的去弄,会给代码执行到来很大的好处。coredata不仅能让我们大大的减少代码量,还最大化的提高运行效率。
就拿NSFetchedResultsController来说吧,他是和UITableView搭配使用的,可以最大化的提高UITableView的UI更新效率,比如我们删除一个东西,只需要执行删除数据库里面的一条信息,然后通过配置NSFetchedResultsController的delegate方法,它自动会找到我们删除的那条信息,然后自动更新UI,最重要的时它不是整体的去更新UITableView,他是只操作了需要删除的哪一个,这就是他的伟大之处。
下面看看我写的这个Demo吧
文件结构:
![](https://img-blog.csdn.net/20140528224922375?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamlqdW55dWFu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
将数据库中得数据放到缓冲区中:
- <span style="font-size:14px;">- (void)viewDidLoad
- {
- [super viewDidLoad];
-
- NSFetchRequest * request = [[NSFetchRequest alloc] init];
- NSEntityDescription * desption = [NSEntityDescription entityForName:TABLE_NAME inManagedObjectContext:[CoreDataManage GetManagedObjectContext]];
- [request setEntity:desption];
-
- NSSortDescriptor * desciptor = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:YES];
- [request setSortDescriptors:[NSArray arrayWithObjects:desciptor, nil nil]];
-
-
-
-
-
-
- NSFetchedResultsController * resultController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:[CoreDataManage GetManagedObjectContext] sectionNameKeyPath:nil cacheName:nil];
- resultController.delegate = self;
- self.fetchController = resultController;
- NSError * error = nil;
-
-
- if ([self.fetchController performFetch:&error])
- {
- NSLog(@"success");
-
- }
- else
- {
- NSLog(@"error = %@",error);
- }
- }
- </span>
配置UITableView
- - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
- {
- return 70;
- }
- - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
- {
-
-
-
-
- if ([[self.fetchController sections] count] > 0) {
- id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchController sections] objectAtIndex:section];
- return [sectionInfo numberOfObjects];
- }
- else
- {
- return 0;
- }
- }
-
- - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- {
- static NSString * mark = @"markIdentifer";
- ContentCell * cell = [tableView dequeueReusableCellWithIdentifier:mark];
- if (cell == nil)
- {
- cell = [[ContentCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:mark];
- }
-
- Student * stu = (Student *)[self.fetchController objectAtIndexPath:indexPath];
- [cell showModel:stu];
- return cell;
- }
配置NSFetchedResultsController的delegate
- <span style="font-size:14px;">
- - (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
- {
- switch (type) {
- case NSFetchedResultsChangeInsert:
- [self.contentTableView insertRowsAtIndexPaths:[NSArray arrayWithObjects:newIndexPath, nil nil] withRowAnimation:UITableViewRowAnimationFade];
- break;
- case NSFetchedResultsChangeDelete:
- [self.contentTableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil nil] withRowAnimation:UITableViewRowAnimationFade];
- break;
- case NSFetchedResultsChangeMove:
- {
- [self.contentTableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil nil] withRowAnimation:UITableViewRowAnimationFade];
- [self.contentTableView insertRowsAtIndexPaths:[NSArray arrayWithObjects:newIndexPath, nil nil] withRowAnimation:UITableViewRowAnimationFade];
- }
- break;
- case NSFetchedResultsChangeUpdate:
- {
- ContentCell * cell1 = (ContentCell *)[self.contentTableView cellForRowAtIndexPath:indexPath];
- Student * stu = (Student *)[controller objectAtIndexPath:indexPath];
- [cell1 showModel:stu];
- }
- break;
-
- default:
- break;
- }
- }
-
-
- - (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
- {
- switch(type) {
-
- case NSFetchedResultsChangeInsert:
- [self.contentTableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
- break;
-
- case NSFetchedResultsChangeDelete:
- [self.contentTableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
- break;
- }
- }
-
-
- - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
- {
- [self.contentTableView beginUpdates];
- }
-
-
- - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
- {
- [self.contentTableView endUpdates];
- }</span><span style="font-size:18px;">
- </span>
添加一个删除按钮的操作,查看效果
- <span style="font-size:14px;">-(NSArray *)searchResult
- {
- NSFetchRequest * request = [[NSFetchRequest alloc] init];
- NSEntityDescription * desption = [NSEntityDescription entityForName:TABLE_NAME inManagedObjectContext:[CoreDataManage GetManagedObjectContext]];
- [request setEntity:desption];
-
- NSError * error = nil;
- NSArray * result = [[CoreDataManage GetManagedObjectContext] executeFetchRequest:request error:&error];
- if (!error)
- {
- [result enumerateObjectsUsingBlock:^(Student * obj, NSUInteger idx, BOOLBOOL *stop) {
- NSLog(@"--%d,%@,%@,%@,%@--/n",idx,obj.studentnumber,obj.name,obj.age,obj.gender);
- }];
-
- }
- else
- {
- NSLog(@"error seach = %@",error);
- }
- return result;
- }
-
-
- -(IBAction)delete:(id)sender
- {
- NSArray * arr = [self searchResult];
- __block Student * deletemp ;
- [arr enumerateObjectsUsingBlock:^(Student * obj, NSUInteger idx, BOOLBOOL *stop) {
- if ([obj.studentnumber intValue] == 2)
- {
- deletemp = obj;
- *stop = YES;
- }
- }];
- if (deletemp)
- {
- [[CoreDataManage GetManagedObjectContext] deleteObject:deletemp];
- NSLog(@"====ok===delete");
- }
- }</span><span style="font-size:18px;">
- </span>
现在编译运行你的应用的话,表面上看起来应该都是一样的,但是如果你看看控制台的话,惊人的事情正在发生:
SELECT 0, t0.Z_PK FROM ZFAILEDBANKINFO t0 LEFT OUTER JOIN
ZFAILEDBANKDETAILS t1 ON t0.ZDETAILS = t1.Z_PK
ORDER BY t1.ZCLOSEDATE DESC
total fetch execution time: 0.0033s for 234 rows.
SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZNAME, t0.ZSTATE, t0.ZCITY,
t0.ZDETAILS FROM ZFAILEDBANKINFO t0 LEFT OUTER JOIN
ZFAILEDBANKDETAILS t1 ON t0.ZDETAILS = t1.Z_PK WHERE
t0.Z_PK IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
ORDER BY t1.ZCLOSEDATE DESC LIMIT 20
total fetch execution time: 0.0022s for 20 rows.
SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZNAME, t0.ZSTATE, t0.ZCITY,
t0.ZDETAILS FROM ZFAILEDBANKINFO t0 LEFT OUTER JOIN
ZFAILEDBANKDETAILS t1 ON t0.ZDETAILS = t1.Z_PK WHERE
t0.Z_PK IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
ORDER BY t1.ZCLOSEDATE DESC LIMIT 20
total fetch execution time: 0.0017s for 20 rows.
你可以看到, NSFetchedResultsController 正在从 FailedBankInfo中按照之前设置的顺序取得大量的ID,根据UITableView的情况每次只缓冲一定数量的数据。比我们直接操控sqlite数据库方便多了。
源码下载