I have a UITableView
with about 500 items.
我有一个UITableView约500项。
When i call tableView.scrollToRow(at: indexPath, at: .bottom, animated: false)
the main UI thread is getting blocked for 3 seconds.
当我调用tableView.scrollToRow(at:indexPath,at:.bottom,animated:false)时,主UI线程被阻止3秒钟。
Is there a way to fix this? or is the problem scrolling 500 items?
有没有办法来解决这个问题?或滚动500项问题?
Thanks
谢谢
the problem is not with reloadData
it was with scrollToRow
问题不在于使用scrollToRow的reloadData
4 个解决方案
#1
2
From discussion about how to use a table view for chat: We can use a table view which uses a transform to flip the Y coordinate. We then need to do the same for each of the cells so they are not upside down.
从讨论如何使用表视图进行聊天:我们可以使用表视图,该视图使用变换来翻转Y坐标。然后我们需要对每个单元格执行相同操作,这样它们就不会颠倒。
The procedure is to build a normal messaging table view where the newest message is on top (instead of bottom). Then put the table view on some superview and invert its coordinate system:
该过程是构建一个正常的消息传递表视图,其中最新消息位于顶部(而不是底部)。然后将表视图放在某些超视图上并反转其坐标系:
chatContainer?.transform = CGAffineTransform(scaleX: 1.0, y: -1.0)
The cell containing the messages should also have some sort of superview for all the contents which needs to be flipped:
包含消息的单元格还应该包含需要翻转的所有内容的某种超级视图:
override func awakeFromNib() {
super.awakeFromNib()
containerView?.transform = CGAffineTransform(scaleX: 1.0, y: -1.0)
}
So the cell is basically flipped twice so it is shown correctly.
因此,单元基本上翻转两次,以便正确显示。
You may find an example project here.
您可以在此处找到示例项目。
#2
0
Use time profiler to identify where exactly is the issue. The thing is that in general the UITableView
performance is not effected by a number of items loaded. The view itself will load as many items as it needs to fill the whole screen.
使用时间分析器来确定问题的确切位置。问题是,一般来说,UITableView性能不受加载的大量项目的影响。视图本身将加载尽可能多的项目以填充整个屏幕。
You may test this by logging a method in a cellForRowAtIndexPath
. So I am guessing this method may be the one that is slow. Check how you access the data from it, maybe there is some heavy logic on it. Or the cell layout may be bugged and very slow.
您可以通过在cellForRowAtIndexPath中记录方法来测试它。所以我猜这个方法可能很慢。检查你如何从中访问数据,也许有一些重要的逻辑。或者单元格布局可能会被窃听并且非常慢。
In a general case if you have extremely large amount of data consider using core data and NSFetchedResultsController
which is designed specifically for this situations. But still note that loading 500 elements in a table view should work smoothly without any special optimizations.
在一般情况下,如果您有非常大量的数据,请考虑使用核心数据和专门为此情况设计的NSFetchedResultsController。但是请注意,在表视图中加载500个元素应该可以顺利运行而无需任何特殊优化。
#3
0
You should do something like this; If user scroll down from top to bottom of the tableview scrollview delegate method fire its "scrollViewDidScroll" method and detect if user bottom of tableview or not then fetch other data and append your array and reload the tableview. Thats it!
你应该这样做;如果用户从tableview的顶部向下滚动,则scrollview委托方法触发其“scrollViewDidScroll”方法,并检测用户是否查看tableview,然后获取其他数据并附加数组并重新加载tableview。而已!
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat actualPosition = scrollView_.contentOffset.y;
CGFloat contentHeight = scrollView_.contentSize.height - (someArbitraryNumber);
if (actualPosition >= contentHeight) {
[self.newsFeedData_ addObjectsFromArray:self.newsFeedData_];
[self.tableView reloadData];
}
}
#4
0
I'm not 100% sure about this solution, didn't had that problem myself. Maybe just dispatch it?
我不是100%肯定这个解决方案,我自己没有遇到这个问题。也许只是派遣它?
extension UITableView {
func tableViewScrollToBottom(animated: Bool) {
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) {
let numberOfSections = self.numberOfSections
let numberOfRows = self.numberOfRows(inSection: numberOfSections-1)
if numberOfRows > 0 {
let indexPath = IndexPath(row: numberOfRows-1, section: (numberOfSections-1))
self.scrollToRow(at: indexPath, at: UITableViewScrollPosition.bottom, animated: animated)
}
}
}
}
#1
2
From discussion about how to use a table view for chat: We can use a table view which uses a transform to flip the Y coordinate. We then need to do the same for each of the cells so they are not upside down.
从讨论如何使用表视图进行聊天:我们可以使用表视图,该视图使用变换来翻转Y坐标。然后我们需要对每个单元格执行相同操作,这样它们就不会颠倒。
The procedure is to build a normal messaging table view where the newest message is on top (instead of bottom). Then put the table view on some superview and invert its coordinate system:
该过程是构建一个正常的消息传递表视图,其中最新消息位于顶部(而不是底部)。然后将表视图放在某些超视图上并反转其坐标系:
chatContainer?.transform = CGAffineTransform(scaleX: 1.0, y: -1.0)
The cell containing the messages should also have some sort of superview for all the contents which needs to be flipped:
包含消息的单元格还应该包含需要翻转的所有内容的某种超级视图:
override func awakeFromNib() {
super.awakeFromNib()
containerView?.transform = CGAffineTransform(scaleX: 1.0, y: -1.0)
}
So the cell is basically flipped twice so it is shown correctly.
因此,单元基本上翻转两次,以便正确显示。
You may find an example project here.
您可以在此处找到示例项目。
#2
0
Use time profiler to identify where exactly is the issue. The thing is that in general the UITableView
performance is not effected by a number of items loaded. The view itself will load as many items as it needs to fill the whole screen.
使用时间分析器来确定问题的确切位置。问题是,一般来说,UITableView性能不受加载的大量项目的影响。视图本身将加载尽可能多的项目以填充整个屏幕。
You may test this by logging a method in a cellForRowAtIndexPath
. So I am guessing this method may be the one that is slow. Check how you access the data from it, maybe there is some heavy logic on it. Or the cell layout may be bugged and very slow.
您可以通过在cellForRowAtIndexPath中记录方法来测试它。所以我猜这个方法可能很慢。检查你如何从中访问数据,也许有一些重要的逻辑。或者单元格布局可能会被窃听并且非常慢。
In a general case if you have extremely large amount of data consider using core data and NSFetchedResultsController
which is designed specifically for this situations. But still note that loading 500 elements in a table view should work smoothly without any special optimizations.
在一般情况下,如果您有非常大量的数据,请考虑使用核心数据和专门为此情况设计的NSFetchedResultsController。但是请注意,在表视图中加载500个元素应该可以顺利运行而无需任何特殊优化。
#3
0
You should do something like this; If user scroll down from top to bottom of the tableview scrollview delegate method fire its "scrollViewDidScroll" method and detect if user bottom of tableview or not then fetch other data and append your array and reload the tableview. Thats it!
你应该这样做;如果用户从tableview的顶部向下滚动,则scrollview委托方法触发其“scrollViewDidScroll”方法,并检测用户是否查看tableview,然后获取其他数据并附加数组并重新加载tableview。而已!
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat actualPosition = scrollView_.contentOffset.y;
CGFloat contentHeight = scrollView_.contentSize.height - (someArbitraryNumber);
if (actualPosition >= contentHeight) {
[self.newsFeedData_ addObjectsFromArray:self.newsFeedData_];
[self.tableView reloadData];
}
}
#4
0
I'm not 100% sure about this solution, didn't had that problem myself. Maybe just dispatch it?
我不是100%肯定这个解决方案,我自己没有遇到这个问题。也许只是派遣它?
extension UITableView {
func tableViewScrollToBottom(animated: Bool) {
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) {
let numberOfSections = self.numberOfSections
let numberOfRows = self.numberOfRows(inSection: numberOfSections-1)
if numberOfRows > 0 {
let indexPath = IndexPath(row: numberOfRows-1, section: (numberOfSections-1))
self.scrollToRow(at: indexPath, at: UITableViewScrollPosition.bottom, animated: animated)
}
}
}
}