CoreData---NSFetchedResultsController和UITableView结合

适用人群:iOS开发。
本文内容:NSFetchedResultsController和UITableView结合适用。

目录:
1.效果图
2.解释
3.代码

1.先上效果图吧:
12338684-3e6ba59d0ee82be4.gif
2.解释

(1)你看着觉得一次性加载这么多数据会不会影响性能。其实呢,NSFetchedResultsController支持对这块的优化,只要设置每次取多少数据, _fetchRequest.fetchBatchSize = 20;,就可以每次从数据库查询20条出来显示,并且效果上看不出任何时间延迟。这个20可自行设置个数,但不要太多。

(2)是不是想问,怎么看NSFetchedResultsController是怎么操作数据库的呢?可以把CoreData操作打印出来,xcode里,打开Edit Scheme...,添加:
-com.apple.CoreData.SQLDebug 1
,如下图:


12338684-0de7bcc9d1fc0f3d.png
设置打印数据库操作

然后再运行程序,就可以实时看到数据库操作过程。
如下图所示,滑动tableview的时候,会每次从数据库取出20条数据:


12338684-d2f0b54874cc2ac0.png

(3)并且,当一些数据不可见时,会及时被回收掉,要显示的时候再重新取数据。这样就会避免数据量特别大的时候,严重占据内存。所以啊,用了NSFetchedResultsController后,不用考虑什么分页加载什么的。

3.代码如下:

备注:UserEntityManager只是提供了context。该文件在CoreData基础篇里有介绍。

#import "ViewController.h"
#import "UserEntityManager.h"

@interface ViewController () <UITableViewDataSource, UITableViewDelegate, NSFetchedResultsControllerDelegate>

@property (nonatomic, strong) NSFetchRequest *fetchRequest;
@property (nonatomic, strong) NSFetchedResultsController *fetchController;
@property (nonatomic, strong) UITableView *tableView;

@property (nonatomic, strong) UserEntityManager *manager;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 添加测试数据
    self.manager = [UserEntityManager new];
//    [self.manager addDatas];
    
    _tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
    _tableView.dataSource = self;
    _tableView.delegate = self;
    _tableView.tableFooterView = [UIView new];
    [self.view addSubview:_tableView];
    
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"UserEntity" inManagedObjectContext:self.manager.context];
    
    NSSortDescriptor *sd = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:NO];
    NSArray *sortDescriptors = [NSArray arrayWithObjects:sd, nil];
    
//    [request setFetchBatchSize:50];//从数据库里每次加载50条数据来筛选数据
//    [request setFetchOffset:10];//读取数据库的游标偏移量,从10开始读取数据
//    [request setFetchLimit:10];//每次要取多少条数据,10就是每次从数据库读取10条数据
    
    _fetchRequest = [[NSFetchRequest alloc] init];
    [_fetchRequest setEntity:entity];
    _fetchRequest.fetchBatchSize = 20;
    [_fetchRequest setSortDescriptors:sortDescriptors];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"remark=%@", @"个性签名"];
    [_fetchRequest setPredicate:predicate];
    
    _fetchController = [[NSFetchedResultsController alloc] initWithFetchRequest:_fetchRequest managedObjectContext:self.manager.context sectionNameKeyPath:nil cacheName:nil];// 需要区分section的时候,设置sectionNameKeyPath,即为用以区分section的表字段名(或路径),不需要的话置为nil即可。
    _fetchController.delegate = self;
    
    BOOL succ = [_fetchController performFetch:nil];
    if (succ) {
        
    }
    
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
       // [self.manager addOneData];
    });
}

- (void)dealloc {
    self.fetchController = nil; // 注意,释放内存
}

#pragma mark - tableView
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    if (self.fetchController) {
        return [self.fetchController sections].count;
    }
    return 0;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (self.fetchController) {
        NSArray *sections = [self.fetchController sections];
        id<NSFetchedResultsSectionInfo> sectionInfo = sections[section];
        return [sectionInfo numberOfObjects];
    }
    return 0;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"123"];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"123"];
    }
    
    UserEntity *user = [self.fetchController objectAtIndexPath:indexPath];
    
    cell.textLabel.text = user.name;
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss:SSS";
    cell.detailTextLabel.text = [formatter stringFromDate: user.date];
    
    return cell;
}

// row改变
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(nullable NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(nullable NSIndexPath *)newIndexPath {
    
    
    if (type == NSFetchedResultsChangeInsert) {
        [self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
    }
    else if (type == NSFetchedResultsChangeDelete) {
        [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }
    else if (type == NSFetchedResultsChangeMove) {
        [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
        [self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
    }
    else if (type == NSFetchedResultsChangeUpdate) {
        [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
    }
    
}
- (void)controllerWillChangeContent:(NSFetchedResultsController*)controller {
    
    [self.tableView beginUpdates];
}
- (void)controllerDidChangeContent:(NSFetchedResultsController*)controller {
    
    [self.tableView endUpdates];
    
//    NSInteger count = self.fetchController.sections[0].numberOfObjects;
//    [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:count-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}

// section改变
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id<NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
    
    switch(type) {
        case NSFetchedResultsChangeInsert:
            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;
        case NSFetchedResultsChangeDelete:
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;
        default:
            break;
    }
    
}

@end

欢迎留言。

猜你喜欢

转载自blog.csdn.net/weixin_34268753/article/details/87374294