我有一个变量,它保存来自 Core Data 的记录集合。有时它可以是数千条记录。如果我将这个变量输入到 Collection View 中,它会自动处理大量数据吗?
我希望集合从 Core Data 延迟加载到变量中,并且 Collection View 一次加载 10-20 个,只是为了处理视口(viewport)。这好得令人难以置信,或者处理这个问题的最佳方法是什么?
最佳答案
我使用 AshFurrow's带有 Collection View 的获取结果 Controller 的实现。 然后当您延迟加载您的获取结果 Controller 时,只需设置您的批量大小。
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Your added implementation
[fetchRequest setFetchBatchSize:20];
// More code...
aFetchedResultsController.delegate = self;
_fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return _fetchedResultsController;
}
下面是 AshFurrow 的 NSFetchedResultsControllerDelegate 实现,我保留原样。然后在您的 Collection View 委托(delegate)/数据源方法中使用您的 fetchedResultsController,这与您在 TableView 中的使用方式非常相似。
// GitHub : AshFurrow FetchedResultsController + CollectionView
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
// Begin updates
_objectChanges = [NSMutableDictionary dictionary];
_sectionChanges = [NSMutableDictionary dictionary];
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeSection:(id<NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
if (type == NSFetchedResultsChangeInsert || type == NSFetchedResultsChangeDelete) {
NSMutableIndexSet *changeSet = _sectionChanges[@(type)];
if (changeSet != nil) {
[changeSet addIndex:sectionIndex];
} else {
_sectionChanges[@(type)] = [[NSMutableIndexSet alloc] initWithIndex:sectionIndex];
}
}
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
NSMutableArray *changeSet = _objectChanges[@(type)];
if (changeSet == nil) {
changeSet = [[NSMutableArray alloc] init];
_objectChanges[@(type)] = changeSet;
}
switch(type) {
case NSFetchedResultsChangeInsert:
[changeSet addObject:newIndexPath];
break;
case NSFetchedResultsChangeDelete:
[changeSet addObject:indexPath];
break;
case NSFetchedResultsChangeUpdate:
[changeSet addObject:indexPath];
break;
case NSFetchedResultsChangeMove:
[changeSet addObject:@[indexPath, newIndexPath]];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
// End updates
NSMutableArray *moves = _objectChanges[@(NSFetchedResultsChangeMove)];
if (moves.count > 0) {
NSMutableArray *updatedMoves = [[NSMutableArray alloc] initWithCapacity:moves.count];
NSMutableIndexSet *insertSections = _sectionChanges[@(NSFetchedResultsChangeInsert)];
NSMutableIndexSet *deleteSections = _sectionChanges[@(NSFetchedResultsChangeDelete)];
for (NSArray *move in moves) {
NSIndexPath *fromIP = move[0];
NSIndexPath *toIP = move[1];
if ([deleteSections containsIndex:fromIP.section]) {
if (![insertSections containsIndex:toIP.section]) {
NSMutableArray *changeSet = _objectChanges[@(NSFetchedResultsChangeInsert)];
if (changeSet == nil) {
changeSet = [[NSMutableArray alloc] initWithObjects:toIP, nil];
_objectChanges[@(NSFetchedResultsChangeInsert)] = changeSet;
} else {
[changeSet addObject:toIP];
}
}
} else if ([insertSections containsIndex:toIP.section]) {
NSMutableArray *changeSet = _objectChanges[@(NSFetchedResultsChangeDelete)];
if (changeSet == nil) {
changeSet = [[NSMutableArray alloc] initWithObjects:fromIP, nil];
_objectChanges[@(NSFetchedResultsChangeDelete)] = changeSet;
} else {
[changeSet addObject:fromIP];
}
} else {
[updatedMoves addObject:move];
}
}
if (updatedMoves.count > 0) {
_objectChanges[@(NSFetchedResultsChangeMove)] = updatedMoves;
} else {
[_objectChanges removeObjectForKey:@(NSFetchedResultsChangeMove)];
}
}
NSMutableArray *deletes = _objectChanges[@(NSFetchedResultsChangeDelete)];
if (deletes.count > 0) {
NSMutableIndexSet *deletedSections = _sectionChanges[@(NSFetchedResultsChangeDelete)];
[deletes filterUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSIndexPath *evaluatedObject, NSDictionary *bindings) {
return ![deletedSections containsIndex:evaluatedObject.section];
}]];
}
NSMutableArray *inserts = _objectChanges[@(NSFetchedResultsChangeInsert)];
if (inserts.count > 0) {
NSMutableIndexSet *insertedSections = _sectionChanges[@(NSFetchedResultsChangeInsert)];
[inserts filterUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSIndexPath *evaluatedObject, NSDictionary *bindings) {
return ![insertedSections containsIndex:evaluatedObject.section];
}]];
}
UICollectionView *collectionView = self.collectionView;
[collectionView performBatchUpdates:^{
NSIndexSet *deletedSections = _sectionChanges[@(NSFetchedResultsChangeDelete)];
if (deletedSections.count > 0) {
[collectionView deleteSections:deletedSections];
}
NSIndexSet *insertedSections = _sectionChanges[@(NSFetchedResultsChangeInsert)];
if (insertedSections.count > 0) {
[collectionView insertSections:insertedSections];
}
NSArray *deletedItems = _objectChanges[@(NSFetchedResultsChangeDelete)];
if (deletedItems.count > 0) {
[collectionView deleteItemsAtIndexPaths:deletedItems];
}
NSArray *insertedItems = _objectChanges[@(NSFetchedResultsChangeInsert)];
if (insertedItems.count > 0) {
[collectionView insertItemsAtIndexPaths:insertedItems];
}
NSArray *reloadItems = _objectChanges[@(NSFetchedResultsChangeUpdate)];
if (reloadItems.count > 0) {
[collectionView reloadItemsAtIndexPaths:reloadItems];
}
NSArray *moveItems = _objectChanges[@(NSFetchedResultsChangeMove)];
for (NSArray *paths in moveItems) {
[collectionView moveItemAtIndexPath:paths[0] toIndexPath:paths[1]];
}
} completion:nil];
_objectChanges = nil;
_sectionChanges = nil;
}
关于ios - Collection View 自动处理大量记录?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30600403/