iOS开发学习之NSFetchedResultsController

应用场合:配合Core Data和Table View使用,Core Data存储数据,Table View显示数据

1.在需要显示数据的视图控制器(包含有table view)中添加NSFetchedResultsController实例变量

@implementation LocationsViewController
{

 NSFetchedResultsController *_fetchedResultsController;

2.惰性实例化NSFetchedResultsController实例变量

-(NSFetchedResultsController *)fetchedResultsController

{

    if(_fetchedResultsController == nil)

    {

        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];  //创建一个请求

    //实体描述

        NSEntityDescription *entity = [NSEntityDescription entityForName:@"Location" inManagedObjectContext:self.managedObjectContext];

        [fetchRequest setEntity:entity];

        //设置排序 

        NSSortDescriptor *sortDescriptor1 = [NSSortDescriptor sortDescriptorWithKey:@"category" ascending:YES];

        NSSortDescriptor *sortDescriptor2 = [NSSortDescriptor sortDescriptorWithKey:@"date" ascending:YES];

        [fetchRequest setSortDescriptors:@[sortDescriptor1,sortDescriptor2]];

    //每次获取20个数据

        [fetchRequest setFetchBatchSize:20];

        

    //按“category”关键字分组,cacheName参数的名字用于唯一标记获取的数据结果,fetchedResultsController会将这些数据缓存起来

        _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"category" cacheName:@"Locations"];

        _fetchedResultsController.delegate = self;

    }

    return _fetchedResultsController;

}

3.让视图控制器实现NSFetchedResultsController协议

@interface LocationsViewController () <NSFetchedResultsControllerDelegate>

@end 

4.调用方法开始获取Core Data存储的数据

-  (void)viewDidLoad {

  [super viewDidLoad];

  [self performFetch];

}

-(void)performFetch

{

    NSError *error;

    if(![self.fetchedResultsController performFetch:&error])

    {

        //添加处理错误情况的代码

        return;

    }

}

5.添加以下代码

- (void)dealloc {

   _fetchedResultsController.delegate = nil;

6.实现table view数据源返回行数的方法

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section];

    return [sectionInfo numberOfObjects];

}

7.获取Core Data存储的某一个数据(实体)时用以下语句,之后便可对该对象进行删除,修改等操作,然后再同步到Core Data数据(参考Core Data博文)

Location *location = [self.fetchedResultsController objectAtIndexPath:indexPath];

8.实现NSFetchedResultsController协议方法

#pragma mark - NSFetchedResultsControllerDelegate

-(void)controllerWillChangeContent:(NSFetchedResultsController *)controller

{

    NSLog(@"*** controllerWillChangeContent");

    [self.tableView beginUpdates];

}

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

{

    switch (type) {

        case NSFetchedResultsChangeInsert:

            NSLog(@"*** NSFetchedResultsChangeInsert (object)");

            [self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];

            break;

        case NSFetchedResultsChangeDelete:

            NSLog(@"*** NSFetchedResultsChangeDelete (object)");

            [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];

            break;

        case NSFetchedResultsChangeUpdate:

            NSLog(@"*** NSFetchedResultsChangeUpdate (object)");

            //添加调用设置table view cell内容的方法,该方法需要另行新建

            break;

        case NSFetchedResultsChangeMove:

            NSLog(@"*** NSFetchedResultsChangeMove (object)");

            [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];

            [self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];

            break;

    }

}

-(void)controller:(NSFetchedResultsController *)controller didChangeSection:(nonnull id<NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type

{

    switch (type) {

        case NSFetchedResultsChangeInsert:

            NSLog(@"*** NSFetchedResultsChangeInsert (section)");

            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];

            break;

        case NSFetchedResultsChangeDelete:

            NSLog(@"*** NSFetchedResultsChangeDelete (section)");

            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];

            break;

        case NSFetchedResultsChangeMove:    break;

        case NSFetchedResultsChangeUpdate:  break;

        

    }

}

-(void)controllerDidChangeContent:(NSFetchedResultsController *)controller

{

    NSLog(@"*** controllerDidChangeContent");

    [self.tableView endUpdates];

}

9.实现以下方法,当滑动删除cell时,同时同步到Core Data数据库

-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(nonnull NSIndexPath *)indexPath

{

    if(editingStyle == UITableViewCellEditingStyleDelete)

    {

        Location *location = [self.fetchedResultsController objectAtIndexPath:indexPath];

        [self.managedObjectContext deleteObject:location];

        

        NSError *error;

        if(![self.managedObjectContext save:&error])

        {

            //添加处理错误情况的代码

            return;

        }

    }

}

10.实现table view分组相关的协议方法

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

{

    return [[self.fetchedResultsController sections] count];

}

-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section

{

    id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section];

    return [sectionInfo name];

}

11.可按以下格式设置cell的显示

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Location"];

  [self configureCell:cell atIndexPath:indexPath];  //configureCell:atIndexPath:方法用于详细设置如何显示cell的内容,需另行编写

  return cell;

}

原文地址:https://www.cnblogs.com/guitarandcode/p/5572366.html