NSFetchedResultsController实例操作与讲解

        学习了NSFetchedResultsController,才深深的体会到coredata的牛逼之处。原来Apple公司弄个新技术,不是平白无故的去弄,会给代码执行到来很大的好处。coredata不仅能让我们大大的减少代码量,还最大化的提高运行效率。

       就拿NSFetchedResultsController来说吧,他是和UITableView搭配使用的,可以最大化的提高UITableView的UI更新效率,比如我们删除一个东西,只需要执行删除数据库里面的一条信息,然后通过配置NSFetchedResultsController的delegate方法,它自动会找到我们删除的那条信息,然后自动更新UI,最重要的时它不是整体的去更新UITableView,他是只操作了需要删除的哪一个,这就是他的伟大之处。

      下面看看我写的这个Demo吧

文件结构:

 

将数据库中得数据放到缓冲区中:

 

  1. - (void)viewDidLoad  
  2. {  
  3.     [super viewDidLoad];  
  4.       
  5.     NSFetchRequest * request = [[NSFetchRequest alloc] init];  
  6.     NSEntityDescription * desption = [NSEntityDescription entityForName:TABLE_NAME inManagedObjectContext:[CoreDataManage GetManagedObjectContext]];  
  7.     [request setEntity:desption];  
  8.   
  9.     NSSortDescriptor * desciptor = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:YES];  
  10.     [request setSortDescriptors:[NSArray arrayWithObjects:desciptor, nil nil]];  
  11.       
  12.     //在CoreData为UITableView提供数据的时候,使用NSFetchedReslutsController能提高体验,因为用NSFetchedReslutsController去读数据的话,能最大效率的读取数据库,也方便数据变化后更新界面,  
  13.     //当我们设置好这个fetch的缓冲值的时候,我们就完成了创建 NSFetchedRequestController 并且将它传递给了fetch请求,但是这个方法其实还有以下几个参数:  
  14.    // 对于managed object 内容,我们值传递内容。  
  15.     //sectionnamekeypath允许我们按照某种属性来分组排列数据内容。  
  16.     //文件名的缓存名字应该被用来处理任何重复的任务,比如说设置分组或者排列数据等。  
  17.     NSFetchedResultsController * resultController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:[CoreDataManage GetManagedObjectContext] sectionNameKeyPath:nil cacheName:nil];  
  18.     resultController.delegate = self;  
  19.     self.fetchController = resultController;  
  20.     NSError * error = nil;  
  21.       
  22.     //操作我们的 fetchedResultsController 并且执行performFetch 方法来取得缓冲的第一批数据。  
  23.     if ([self.fetchController performFetch:&error])  
  24.     {  
  25.         NSLog(@"success");  
  26.        // NSLog(@"=======%@",[self.fetchController])  
  27.     }  
  28.     else  
  29.     {  
  30.         NSLog(@"error = %@",error);  
  31.     }  
  32. }  
  33. </span>  


配置UITableView

 

 
  1. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath  
  2. {  
  3.     return 70;  
  4. }  
  5. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section  
  6. {  
  7.     //section配置  
  8.    // return [[self.fetchController sections] count];  
  9.       
  10.     //row配置  
  11.     if ([[self.fetchController sections] count] > 0) {  
  12.         id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchController sections] objectAtIndex:section];  
  13.         return [sectionInfo numberOfObjects];  
  14.     }  
  15.     else  
  16.     {  
  17.         return 0;  
  18.     }  
  19. }  
  20.   
  21. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath  
  22. {  
  23.     static NSString * mark = @"markIdentifer";  
  24.     ContentCell * cell = [tableView dequeueReusableCellWithIdentifier:mark];  
  25.     if (cell == nil)  
  26.     {  
  27.         cell = [[ContentCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:mark];  
  28.     }  
  29.       
  30.     Student * stu = (Student *)[self.fetchController objectAtIndexPath:indexPath];  
  31.     [cell showModel:stu];  
  32.     return cell;  
  33. }  



 

配置NSFetchedResultsController的delegate

 

 
  1. <span style="font-size:14px;">//当数据发生变化时,点对点的更新tableview,这样大大的提高了更新效率  
  2. - (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath  
  3. {  
  4.     switch (type) {  
  5.         case NSFetchedResultsChangeInsert:  
  6.             [self.contentTableView insertRowsAtIndexPaths:[NSArray arrayWithObjects:newIndexPath, nil nil] withRowAnimation:UITableViewRowAnimationFade];  
  7.             break;  
  8.         case NSFetchedResultsChangeDelete:  
  9.             [self.contentTableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil nil] withRowAnimation:UITableViewRowAnimationFade];  
  10.             break;  
  11.         case NSFetchedResultsChangeMove:  
  12.         {  
  13.             [self.contentTableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil nil] withRowAnimation:UITableViewRowAnimationFade];  
  14.             [self.contentTableView insertRowsAtIndexPaths:[NSArray arrayWithObjects:newIndexPath, nil nil] withRowAnimation:UITableViewRowAnimationFade];  
  15.         }  
  16.             break;  
  17.         case NSFetchedResultsChangeUpdate:  
  18.         {  
  19.             ContentCell * cell1 = (ContentCell *)[self.contentTableView cellForRowAtIndexPath:indexPath];  
  20.             Student * stu = (Student *)[controller objectAtIndexPath:indexPath];  
  21.             [cell1 showModel:stu];  
  22.         }  
  23.             break;  
  24.               
  25.         default:  
  26.             break;  
  27.     }  
  28. }  
  29.   
  30. //点对点的更新section  
  31. - (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type  
  32. {  
  33.     switch(type) {  
  34.               
  35.         case NSFetchedResultsChangeInsert:  
  36.             [self.contentTableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];  
  37.             break;  
  38.               
  39.         case NSFetchedResultsChangeDelete:  
  40.             [self.contentTableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];  
  41.             break;  
  42.     }  
  43. }  
  44.   
  45. //此方法执行时,说明数据已经发生了变化,通知tableview开始更新UI  
  46. - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller  
  47. {  
  48.     [self.contentTableView beginUpdates];  
  49. }  
  50.   
  51. //结束更新  
  52. - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller  
  53. {  
  54.     [self.contentTableView endUpdates];  
  55. }</span><span style="font-size:18px;">  
  56. </span>  


添加一个删除按钮的操作,查看效果

 

 
  1. <span style="font-size:14px;">-(NSArray *)searchResult  
  2. {  
  3.     NSFetchRequest * request = [[NSFetchRequest alloc] init];  
  4.     NSEntityDescription * desption = [NSEntityDescription entityForName:TABLE_NAME inManagedObjectContext:[CoreDataManage GetManagedObjectContext]];  
  5.     [request setEntity:desption];  
  6.       
  7.     NSError * error = nil;  
  8.     NSArray * result = [[CoreDataManage GetManagedObjectContext] executeFetchRequest:request error:&error];  
  9.     if (!error)  
  10.     {  
  11.         [result enumerateObjectsUsingBlock:^(Student * obj, NSUInteger idx, BOOLBOOL *stop) {  
  12.             NSLog(@"--%d,%@,%@,%@,%@--/n",idx,obj.studentnumber,obj.name,obj.age,obj.gender);  
  13.         }];  
  14.           
  15.     }  
  16.     else  
  17.     {  
  18.         NSLog(@"error seach  = %@",error);  
  19.     }  
  20.     return result;  
  21. }  
  22.   
  23.   
  24. -(IBAction)delete:(id)sender  
  25. {  
  26.     NSArray * arr = [self searchResult];  
  27.     __block Student * deletemp ;  
  28.     [arr enumerateObjectsUsingBlock:^(Student * obj, NSUInteger idx, BOOLBOOL *stop) {  
  29.         if ([obj.studentnumber intValue] == 2)  
  30.         {  
  31.             deletemp = obj;  
  32.             *stop = YES;  
  33.         }  
  34.     }];  
  35.     if (deletemp)  
  36.     {  
  37.         [[CoreDataManage GetManagedObjectContext] deleteObject:deletemp];  
  38.         NSLog(@"====ok===delete");  
  39.     }  
  40. }</span><span style="font-size:18px;">  
  41. </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数据库方便多了。

posted @ 2016-07-21 16:55  luqinbin  阅读(390)  评论(0编辑  收藏  举报