认识CoreData—高级用法

  }

  }

  }

  上面是UITableView的代理方法,代理方法中嵌套了FRC的数据获取代码,这样在刷新视图时就可以保证使用最新的数据。并且在代码中简单实现了删除cell后,通过MOC调用删除操作,使本地持久化数据和UI保持一致。

  就像上面cellForRowAtIndexPath:方法中使用的一样,FRC提供了两个方法轻松转换indexPath和NSManagedObject的对象,在实际开发中这两个方法非常实用,这也是FRC和UITableView、UICollectionView深度融合的表现。

  - (id)objectAtIndexPath:(NSIndexPath *)indexPath;

  - (nullable NSIndexPath *)indexPathForObject:(id)object;

  Fetched Results Controller Delegate

  // Cell数据源发生改变会回调此方法,例如添加新的托管对象等

  - (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(nullable NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(nullable NSIndexPath *)newIndexPath {

  switch (type) {

  case NSFetchedResultsChangeInsert:

  [tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];

  break;

  case NSFetchedResultsChangeDelete:

  [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];

  break;

  case NSFetchedResultsChangeMove:

  [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];

  [tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];

  break;

  case NSFetchedResultsChangeUpdate: {

  UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

  Employee *emp = [fetchedResultController objectAtIndexPath:indexPath];

  cell.textLabel.text = emp.name;

  }

  break;

  }

  }

  // Section数据源发生改变回调此方法,例如修改section title等。

  - (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id

  )sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {

  switch (type) {

  case NSFetchedResultsChangeInsert:

  [tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic];

  break;

  case NSFetchedResultsChangeDelete:

  [tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic];

  break;

  default:

  break;

  }

  }

  // 本地数据源发生改变,将要开始回调FRC代理方法。

  - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {

  [tableView beginUpdates];

  }

  // 本地数据源发生改变,FRC代理方法回调完成。

  - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {

  [tableView endUpdates];

  }

  // 返回section的title,可以在这里对title做进一步处理。这里修改title后,对应section的indexTitle属性会被更新。

  - (nullable NSString *)controller:(NSFetchedResultsController *)controller sectionIndexTitleForSectionName:(NSString *)sectionName {

  return [NSString stringWithFormat:@"sectionName %@", sectionName];

  }

  上面就是当本地持久化数据发生改变后,被回调的FRC代理方法的实现,可以在对应的实现中完成自己的代码逻辑。

  在上面的章节中讲到删除cell后,本地持久化数据同步的问题。在删除cell后在tableView代理方法的回调中,调用了MOC的删除方法,使本地持久化存储和UI保持同步,并回调到下面的FRC代理方法中,在代理方法中对UI做删除操作,这样一套由UI的改变引发的删除流程就完成了。

  目前为止已经实现了数据和UI的双向同步,即UI发生改变后本地存储发生改变,本地存储发生改变后UI也随之改变。可以通过下面添加数据的代码来测试一下,NSFetchedResultsController就讲到这里了。

  - (void)addMoreData {

  Employee *employee = [NSEntityDescription insertNewObjectForEntityForName:@"Employee" inManagedObjectContext:context];

  employee.name = [NSString stringWithFormat:@"lxz 15"];

  employee.height = @(15);

  employee.brithday = [NSDate date];

  employee.sectionName = [NSString stringWithFormat:@"3"];

  NSError *error = nil;

  if (![context save:&error]) {