Collection View 自动处理大量记录?
Posted
技术标签:
【中文标题】Collection View 自动处理大量记录?【英文标题】:Collection View automatically handles large amounts of records? 【发布时间】:2015-06-02 15:32:15 【问题描述】:我有一个变量,其中包含来自 Core Data 的记录集合。有时可能是数千条记录。如果我将此变量输入到集合视图中,它会自动处理大量吗?
我希望集合是从 Core Data 延迟加载到变量中的,并且集合视图一次加载 10-20 个,只是为了处理视口。这真是太好了,还是最好的处理方法是什么?
【问题讨论】:
【参考方案1】:我使用AshFurrow's 实现带有集合视图的获取结果控制器。 然后,当您延迟加载获取的结果控制器时,只需设置批量大小。
- (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 实现,我保留原样。然后在您的集合视图委托/数据源方法中使用您的 fetchedResultsController,这与您在表格视图中的使用方式非常相似。
// 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;
【讨论】:
【参考方案2】:如果您在集合视图中时记录会发生变化并且您想要跟踪它,请使用获取的结果控制器。它们是为表格视图设计的,但足够简单以适应集合视图。
否则,请为您的提取请求设置批量大小。这将确保一次仅从存储中获取一定数量的记录,如果不访问它们将转回故障。来自文档:
如果您设置非零批量大小,则执行提取时返回的对象集合将分成多个批次。执行 fetch 时,会评估整个请求并记录所有匹配对象的身份,但一次从持久存储中获取不超过 batchSize 对象的数据。执行请求返回的数组将是一个代理对象,可以根据需要透明地对批次进行故障处理。 (在数据库术语中,这是一个内存游标。)
【讨论】:
以上是关于Collection View 自动处理大量记录?的主要内容,如果未能解决你的问题,请参考以下文章
您好,我正在使用 Collection View 单元格,我想记录其中有多少被单击“变为真”并返回下一个视图控制器
Redux记录:Store是如何自动调用reducers来处理action的
从 Collection View Xcode 中删除 Collection View Cell
ScrollTo indexPath 在 Collection View Cell 内的 Collection View (Nested CollectionView)