好的,我需要的是当新元素添加到当前可见行之上时阻止tableview滚动。我正在使用带有大量对象的NSFetchedResultsController(如10 000),当我没有触及contentOffset时,reloadData非常流畅。
但是,当我尝试操作contentOffset以在插入新条目时保持滚动位置时,它开始冻结用户界面300毫秒,这对我不利。
有人建议在顶部添加新项目时如何将tableview保持在同一单元格的更好(更快)的解决方案吗?
这是我目前用于跟踪插入和移动contentOffset的代码。它不支持动画和不同的单元格大小。
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
switch(type) {
case NSFetchedResultsChangeInsert:
[_insertions addObject:@(newIndexPath.row)];
break;
}
}
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
_insertions = @[].mutableCopy;
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
NSMutableArray *copy = _insertions.mutableCopy;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSSortDescriptor *lowestToHighest = [NSSortDescriptor sortDescriptorWithKey:@"self" ascending:YES];
[copy sortUsingDescriptors:[NSArray arrayWithObject:lowestToHighest]];
dispatch_sync(dispatch_get_main_queue(), ^{
for (NSNumber *i in copy) {
[self p_delayedAddRowAtIndex:[i integerValue]];
}
[self.tableView reloadData];
});
});
}
- (CGFloat)p_firstRowHeight {
return [self tableView:[self tableView] heightForRowAtIndexPath:[NSIndexPath indexPathForRow:0
inSection:0]];
}
-(void)p_delayedAddRowAtIndex:(NSInteger)row {
NSIndexPath *firstVisibleIndexPath = [[self.tableView indexPathsForVisibleRows] firstObject];
if (firstVisibleIndexPath.row >= row) {
CGPoint offset = [[self tableView] contentOffset];
offset.y += [self firstRowHeight];
if ([self.tableView visibleCells].count > self.tableView.frame.size.height / [self firstRowHeight]) {
[[self tableView] setContentOffset:offset];
}
}
}
答案 0 :(得分:2)
好的,经过一些让我指向正确方向的回应后,我想出了这个解决方案。虽然做了一些丑陋的坐标数学并且不支持不同的单元格大小,但它工作顺畅。希望它对某人有所帮助。
-(void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
NSIndexPath *firstVisible = [[self.tableView indexPathsForVisibleRows] firstObject];
self.topVisibleMessage = [self.fetchedResultsController objectAtIndexPath:firstVisible];
NSIndexPath *topIndexPath = [self.fetchedResultsController indexPathForObject:self.topVisibleMessage];
self.cellOffset = self.tableView.contentOffset.y - topIndexPath.row * [self firstRowHeight];
}
-(void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.tableView reloadData];
if (self.topVisibleMessage) {
NSIndexPath *topIndexPath = [self.fetchedResultsController indexPathForObject:self.topVisibleMessage];
CGPoint point = {0, topIndexPath.row * [self firstRowHeight] + self.cellOffset};
[self.tableView setContentOffset:point];
}
}
答案 1 :(得分:0)
您的任务可能熟悉许多新闻源应用程序列表视图。你看过那些应用了吗?他们可能会有某种解决方案。据我所知,保持表格视图位置的唯一方法是scrollRectToVisible:animated:
。
许多社交网络应用程序都有熟悉的方法来插入新的单元格。当有更新时,会在视图顶部显示小通知,并显示消息(" 5个新项目"),其中包含单元格并自动滚动到顶部。