ios UITableView 刷新而不滚动
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25589540/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
UITableView Refresh without scrolling
提问by ColdSteel
I have a _TableView
with items , and I want to set automatic refresh,and I don't want it to scroll on refresh , lets say user scrolled 2 pages down , and the refresh trigered -> so I want to put the refreshed content to the top of the table without interupting user's scrolling
我有一个_TableView
项目,我想设置自动刷新,我不希望它在刷新时滚动,假设用户向下滚动了 2 页,并且触发了刷新 -> 所以我想将刷新的内容放到不中断用户滚动的表格顶部
Assume user was on row 18
and now the _dataSource
is refreshed so it fetched lets say 4 items , so I want user to stay on the item he was.
假设用户在第 18 行,现在_dataSource
刷新了,所以它提取了 4 个项目,所以我希望用户留在他所在的项目上。
What would be the best approach to achieve it ??
实现它的最佳方法是什么?
采纳答案by Prasad
I am showing if only one row is being added. You can extend it to multiple rows.
我正在显示是否只添加了一行。您可以将其扩展到多行。
// dataArray is your data Source object
[dataArray insertObject:name atIndex:0];
CGPoint contentOffset = self.tableView.contentOffset;
contentOffset.y += [self tableView:self.tableView heightForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
[self.tableView reloadData];
[self.tableView setContentOffset:contentOffset];
But for this to work you need to have defined - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
the method. Or else, you can directly give your tableview row height if it is constant.
但是要使其工作,您需要定义- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
该方法。否则,如果它是恒定的,你可以直接给你的 tableview 行高。
回答by David Seek
For Swift 3+:
对于Swift 3+:
You need to save the current offset of the UITableView
, then reload and then set the offset back on the UITableView
.
您需要保存 的当前偏移量UITableView
,然后重新加载,然后将偏移量设置回UITableView
.
I have created this function for this purpose:
我为此目的创建了这个函数:
func reload(tableView: UITableView) {
let contentOffset = tableView.contentOffset
tableView.reloadData()
tableView.layoutIfNeeded()
tableView.setContentOffset(contentOffset, animated: false)
}
Simply call it with: reload(tableView: self.tableView)
简单地调用它: reload(tableView: self.tableView)
回答by Trung Phan
SWIFT 3
斯威夫特 3
let contentOffset = self.tableView.contentOffset
self.tableView.reloadData()
self.tableView.layoutIfNeeded()
self.tableView.setContentOffset(contentOffset, animated: false)
This is error of iOS8 when using UITableViewAutomatic Dimension. We need store the content offset of table, reload table, force layout and set contenOffset back.
这是使用 UITableViewAutomatic Dimension 时 iOS8 的错误。我们需要存储表的内容偏移量,重新加载表,强制布局并将 contenOffset 设置回来。
CGPoint contentOffset = self.tableView.contentOffset;
[self.tableView reloadData];
[self.tableView layoutIfNeeded];
[self.tableView setContentOffset:contentOffset];
回答by COVID19
Just set estimatedRowHeight
to maximum possible value.
只需设置estimatedRowHeight
为最大可能值。
self.tableView.estimatedRowHeight = 1000
self.tableView.estimatedSectionFooterHeight = 100.0
self.tableView.estimatedSectionHeaderHeight = 500.0
That's it!!
就是这样!!
Note:
笔记:
Please do not use FLT_MAX, DBL_MAX
value. May be it will crash your app.
请不要FLT_MAX, DBL_MAX
使用价值。可能会使您的应用程序崩溃。
回答by Marco M
I'm doing it this way:
我是这样做的:
messages.insertContentsOf(incomingMsgs.reverse(), at: 0)
table.reloadData()
// This is for the first load, first 20 messages, scroll to bottom
if (messages.count <= 20) {
let indexToScroll = NSIndexPath(forRow: saferSelf.messages.count - 1, inSection: 0)
table.scrollToRowAtIndexPath(indexToScroll, atScrollPosition: .Top , animated: false)
}
// This is to reload older messages on top of tableview
else {
let indexToScroll = NSIndexPath(forRow: incomingMsgs.count, inSection: 0)
table.scrollToRowAtIndexPath(indexToScroll, atScrollPosition: .Top , animated: false)
// Remove the refreshControl.height + tableHeader.height from the offset so the content remain where it was before reload
let theRightOffset = CGPointMake(0, table.contentOffset.y - refreshControl.frame.height - table.headeView.frame.height)
table.setContentOffset(theRightOffset, animated: false)
}
...also, since I use dynamic cell height, to avoid some weirdness, the estimation is cached:
...此外,由于我使用动态单元格高度,为了避免一些奇怪的情况,估计被缓存:
var heightAtIndexPath = [NSIndexPath: CGFloat]()
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return heightAtIndexPath[indexPath] ?? UITableViewAutomaticDimension
}
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
heightAtIndexPath[indexPath] = cell.frame.height
}
回答by JhanviR
This code will prevent unnecessary animation and maintain the scroll view's content offset, it worked fine for me.
这段代码将防止不必要的动画并保持滚动视图的内容偏移,对我来说效果很好。
let lastScrollOffset = tableView.contentOffset
tableView.beginUpdates()
tableView.reloadData()
tableView.endUpdates()
tableView.layer.removeAllAnimations()
tableView.setContentOffset(lastScrollOffset, animated: false)
回答by Yifan
Use Extension
使用扩展
create UITableViewExtensions.swift
and add following:
创建UITableViewExtensions.swift
并添加以下内容:
extension UITableView {
func reloadDataWithoutScroll() {
let offset = contentOffset
reloadData()
layoutIfNeeded()
setContentOffset(offset, animated: false)
}
}
回答by ZAFAR007
Swift 4.2 :Simple Solution
Swift 4.2:简单的解决方案
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.estimatedRowHeight = 0
self.tableView.estimatedSectionHeaderHeight = 0
self.tableView.estimatedSectionFooterHeight = 0
}
//And then simply update(insert, reloadSections, delete etc) your tableView or reload
tableView.reloadData()
//or
UIView.performWithoutAnimation {
tableView.beginUpdates()
.....
tableView.endUpdates()
}
回答by Pankaj Kulkarni
In iOS 12.x
, using Xcode 10.2.1
, an easier option is.
在 中iOS 12.x
,使用Xcode 10.2.1
,更简单的选择是。
UIView.performWithoutAnimation {
let loc = tableView.contentOffset
tableView.reloadRows(at: [indexPath], with: .none)
tableView.contentOffset = loc
}
This works better than following; it shakes at times when the row is not fully visible.
这比以下更有效;当行不完全可见时,它有时会震动。
let contentOffset = self.tableView.contentOffset
self.tableView.reloadData()
self.tableView.layoutIfNeeded()
self.tableView.setContentOffset(contentOffset, animated: false)
回答by Hyman Chen
try to replace
尝试更换
reloadData
with
reloadData
和
tableView.reloadRows
(at: tableView!.indexPathsForVisibleRows!, with: .none
),
tableView.reloadRows
( at: tableView!.indexPathsForVisibleRows!, with: .none
),
but you should be care about no cells
, if no cells
, this method should cause crash.
但是你应该关心no cells
,如果no cells
,这个方法会导致崩溃。