ios – 核心数据NSFetchedResultsController和批量大小设置加载所有行

我的核心数据数据库中有数千个点,我想将它们全部放在我的tableView中,但我不想一次性将它们提取到内存中,但是我想使用NSFetchedResultsController并用一些常量批量处理它们.我设置它就像我在许多教程中看到的那样,我设置了fetchBatchSize属性,但是在显示之前加载视图控制器花了几秒钟.

在viewDidLoad中调用函数

- (void)initPositionsFetch {
    // Initialize Fetch Request
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"OpenPositionCD"];

    // Add Sort Descriptors
    [fetchRequest setSortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"timestamp" ascending:NO]]];

    // Add predicate
    [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"moduleId == %@",_module.moduleId]];

    [fetchRequest setFetchBatchSize:100];

    [fetchRequest setIncludesPendingChanges:NO];

    // Initialize Fetched Results Controller
    self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:temporaryContext sectionNameKeyPath:nil cacheName:nil];

    // Configure Fetched Results Controller
    [self.fetchedResultsController setDelegate:self];

    // Perform Fetch
    NSError *error = nil;
    [self.fetchedResultsController performFetch:&error];

    if (error) {
        NSLog(@"Unable to perform fetch.");
        NSLog(@"%@,%@",error,error.localizedDescription);
    }
}

NSFetchedResultsControllerDelegate方法

#pragma mark - NSFetchedResultsControllerDelegate
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView beginUpdates];
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView endUpdates];
}

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
    switch (type) {
        case NSFetchedResultsChangeInsert: {
            [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
        }
        case NSFetchedResultsChangeDelete: {
            [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
        }
        case NSFetchedResultsChangeUpdate: {
            [self configureCell:(PanelPositionCell *)[self.tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            break;
        }
        case NSFetchedResultsChangeMove: {
            [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
        }
    }
}

UITableView委托方法

#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    if (_tracksVisible)
        return 1;
    else
        return [[self.fetchedResultsController sections] count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (_tracksVisible)
        return [_tracks count];
    else {
        NSArray *sections = [self.fetchedResultsController sections];
        id<NSFetchedResultsSectionInfo> sectionInfo = [sections objectAtIndex:section];

        return [sectionInfo numberOfObjects];
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier;
    if(_tracksVisible)
        CellIdentifier = TrackCellIdentifier;
    else
        CellIdentifier = PositionCellIdentifier;

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    if(_tracksVisible) {
        [((PanelTrackCell *)cell) setValuesByTrackCD:[_tracks objectAtIndex:indexPath.row]];
    } else  {
        [self configureCell:(PanelPositionCell *)cell atIndexPath:indexPath];
    }

    return cell;
}

- (void)configureCell:(PanelPositionCell *)cell atIndexPath:(NSIndexPath *)indexPath {
    // Fetch Record
    NSManagedObject *record = [self.fetchedResultsController objectAtIndexPath:indexPath];
    OpenPositionCD *position = (OpenPositionCD *)record;

    // Update Cell
    [cell setValuesByOpenPositionCD:position];
}

这有什么问题?为什么要加载所有行?可能是Core Data模型的问题?我试图删除谓词,但它没有帮助.必须设置SortDescriptor,但这只是我想到的问题所在.我希望结果按时间戳排序.时间戳是Date属性,设置为Indexed.首先我必须得到它然后我可以按时间对它们进行排序,如何对结果进行批处理?我使用tableView通过switch(_tracksVisible)显示另一个数据应该不是问题,对吧?

我甚至尝试使用以下代码后台获取结果:

[[[self fetchedResultsController] managedObjectContext] performBlock:^{
        NSError *error = nil;
    [self.fetchedResultsController performFetch:&error];

    if (error) {
        NSLog(@"Unable to perform fetch.");
        NSLog(@"%@,error.localizedDescription);
    }
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            [_tableView reloadData];
        }];
}];

发生了什么事情,控制器显示得更早,但随后UI冻结,几乎与以前相同.

解决方法

在BatchSize中尝试使用较低的值,可能是20

[fetchRequest setFetchBatchSize:20];

您也可以尝试添加initPositionFetch

[fetchRequest setFetchLimit:20];

相关文章

背景 前端时间产品经理决定使用百度统计,使得 工程B 中原统计sdk-友盟统计,需要被去除。之前尝试去除...
结论: alloc负责分配内存和创建对象对应的isa指针; init只是返回alloc生成的对象。 所以alloc后,多次...
更新 如果UI愿意把启动图切割成n份,按一定约束在launchscreen.storyboard中进行排版,启动图效果会更好...
最近在看一本书《Effective OC 2.0》,今天看到有个tip是OC适中循环各自优劣性,作者最终推荐此块循环。...
// // ViewController.m // paintCodeTestOC //gif // Created by LongMa on 2019/7/25. // #import &a...
背景介绍 一般情况下,出于省电、权限、合理性等因素考虑,给人的感觉是很多奇怪的需求安卓可以实现,但...