}
}
}
上面是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]) {