NSFetchedResultsController实例操作与讲解

it2022-05-09  20

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

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

      下面看看我写的这个Demo吧

文件结构:

 

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

 

- (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]];            //在CoreData为UITableView提供数据的时候,使用NSFetchedReslutsController能提高体验,因为用NSFetchedReslutsController去读数据的话,能最大效率的读取数据库,也方便数据变化后更新界面,      //当我们设置好这个fetch的缓冲值的时候,我们就完成了创建 NSFetchedRequestController 并且将它传递给了fetch请求,但是这个方法其实还有以下几个参数:     // 对于managed object 内容,我们值传递内容。      //sectionnamekeypath允许我们按照某种属性来分组排列数据内容。      //文件名的缓存名字应该被用来处理任何重复的任务,比如说设置分组或者排列数据等。      NSFetchedResultsController * resultController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:[CoreDataManage GetManagedObjectContext] sectionNameKeyPath:nil cacheName:nil];      resultController.delegate = self;      self.fetchController = resultController;      NSError * error = nil;            //操作我们的 fetchedResultsController 并且执行performFetch 方法来取得缓冲的第一批数据。      if ([self.fetchController performFetch:&error])      {          NSLog(@"success");         // NSLog(@"=======%@",[self.fetchController])      }      else      {          NSLog(@"error = %@",error);      }  }  </span>  

配置UITableView

 

  - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath  {      return 70;  }  - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section  {      //section配置     // return [[self.fetchController sections] count];            //row配置      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;">//当数据发生变化时,点对点的更新tableview,这样大大的提高了更新效率  - (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;      }  }    //点对点的更新section  - (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;      }  }    //此方法执行时,说明数据已经发生了变化,通知tableview开始更新UI  - (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数据库方便多了。

转载于:https://www.cnblogs.com/luqinbin/p/5692398.html

相关资源:数据结构—成绩单生成器

最新回复(0)