【发布时间】:2015-10-20 16:16:31
【问题描述】:
我的核心数据数据库中有数千个点,我希望将它们全部放在我的 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];
}
这有什么问题?为什么它加载所有行?核心数据模型可能有问题吗?我试图删除谓词,但没有帮助。 SortDescriptor 必须设置,但这是我想到的唯一可能有问题的地方。我希望结果按时间戳排序。 Timestamp 是 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, error.localizedDescription);
}
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[_tableView reloadData];
}];
}];
发生的情况是控制器显示得更早,但随后 UI 冻结,所需时间几乎与以前相同。
【问题讨论】:
标签: ios objective-c uitableview core-data nsfetchedresultscontroller