我有一个_TableView
项目,我想设置自动刷新,我不希望它滚动刷新,让我们说用户滚动2页,并刷新trigered - >所以我想把刷新的内容表的顶部没有插入用户的滚动
假设用户在第18行,现在_dataSource
被刷新,所以它获取了4个项目,所以我希望用户留在他的项目上。
实现它的最佳方法是什么?
我正在显示是否只添加了一行。您可以将其扩展为多行。
// 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];
但要实现这一点,您需要定义- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
方法。或者,如果它是常量,您可以直接给出tableview行高。
当你想重新加载时,你必须
self.tableView.reloadData()
self.tableView.layoutIfNeeded()
并使用这个UITableViewDelegate
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 'your maximum cell's height'
}
并且您的tableView将保留在上一个滚动位置而不滚动
在iOS 12.x
,使用Xcode 10.2.1
,更容易的选择。
UIView.performWithoutAnimation {
let loc = tableView.contentOffset
tableView.reloadRows(at: [indexPath], with: .none)
tableView.contentOffset = loc
}
这比以下更好;当行不完全可见时,它会摇晃。
let contentOffset = self.tableView.contentOffset
self.tableView.reloadData()
self.tableView.layoutIfNeeded()
self.tableView.setContentOffset(contentOffset, animated: false)
对于Swift 3+:
您需要保存UITableView
的当前偏移量,然后重新加载,然后在UITableView
上设置偏移量。
我为此创建了这个函数:
func reload(tableView: UITableView) {
let contentOffset = tableView.contentOffset
tableView.reloadData()
tableView.layoutIfNeeded()
tableView.setContentOffset(contentOffset, animated: false)
}
只需将其命名为:reload(tableView: self.tableView)
SWIFT 3
let contentOffset = self.tableView.contentOffset
self.tableView.reloadData()
self.tableView.layoutIfNeeded()
self.tableView.setContentOffset(contentOffset, animated: false)
使用UITableViewAutomatic Dimension时,这是iOS8的错误。我们需要存储表的内容偏移,重载表,强制布局和设置contenOffset。
CGPoint contentOffset = self.tableView.contentOffset;
[self.tableView reloadData];
[self.tableView layoutIfNeeded];
[self.tableView setContentOffset:contentOffset];
我是这样做的:
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)
}
...此外,由于我使用动态单元格高度,以避免一些奇怪,估计缓存:
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
}
只需将estimatedRowHeight
设置为最大可能值即可。
self.tableView.estimatedRowHeight = 1000
而已!!
注意:请不要使用FLT_MAX, DBL_MAX
值。可能会崩溃你的应用程序。
此代码将防止不必要的动画并保持滚动视图的内容偏移,它对我来说很好。
let lastScrollOffset = tableView.contentOffset
tableView.beginUpdates()
tableView.reloadData()
tableView.endUpdates()
tableView.layer.removeAllAnimations()
tableView.setContentOffset(lastScrollOffset, animated: false)
使用扩展
创建UITableViewExtensions.swift
并添加以下内容:
extension UITableView {
func reloadDataWithoutScroll() {
let offset = contentOffset
reloadData()
layoutIfNeeded()
setContentOffset(offset, animated: false)
}
}
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()
}
试着替换
reloadData
与
tableView.reloadRows
(at: tableView!.indexPathsForVisibleRows!, with: .none
),
但你应该关心no cells
,如果no cells
,这种方法应该导致崩溃。