[英]iOS TableView ScrollToRow Empty Screen Problem
我正在尝试使用 scrollToRow 但是当调用此方法时,tableview 有时不显示任何数据。 当我检查 UI 检查器时,我可以看到表格单元格,但在屏幕上看不到。
我试过 DispactQueue 没有解决这个问题
var forIndex = 0
for item in filteredData {
if let firstCharacter = item.Name?.prefix(1), firstCharacter == char {
let indexpath = IndexPath(row: forIndex, section: 0)
self.tableView.reloadRows(at: [indexpath], with: UITableView.RowAnimation.top)
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500), execute: { [weak self] in
self?.tableView.scrollToRow(at: indexpath, at: UITableView.ScrollPosition.top, animated: true)
})
break
}
forIndex += 1
}
char 是列表的元素,如 a、b、c、d... FilteredData 是 tableview 元素的列表
调试 scrollToRow 方法是否标记断点时它正在工作
可能是reloadRows (at:)
animation 仍在进行中,当你踢下一个导致这种奇怪的行为时。
使用断点, reloadRows (at:)
有机会完成并continuing
scrollToRow
之后开始。
假设您的数据源没有问题,如果这对您的情况有帮助,请尝试以下操作之一:
1.改变
tableView.reloadRows(at: [indexpath], with: .top)
到
tableView.reloadRows(at: [indexpath], with: .none)
以便 UITableView 应用默认值 animation
或者
2.在开始下一个animation之前增加你的延迟
或者
3.在没有animation的情况下执行重新加载
UIView.performWithoutAnimation { [weak self] in
self?.tableView.reloadRows(at: [indexpath], with: .none)
}
tableView.scrollToRow(at: indexpath,
at: UITableView.ScrollPosition.top,
animated: true)
或者
4. 使用beginUpdates
和endUpdates
这在对表视图执行批操作时很有用
tableView.beginUpdates()
tableView.reloadRows(at: [indexpath], with: .top)
tableView.scrollToRow(at: indexpath,
at: UITableView.ScrollPosition.top,
animated: true)
tableView.endUpdates()
这些是否会给您带来更好的结果?
更新
更多地查看reloadRows(at indexPaths:
的文档,这里有一些对我来说很突出的行
如果您想提醒用户单元格的值正在更改,请调用此方法。 但是,如果通知用户并不重要——也就是说,您只想更改单元格显示的值——您可以获取特定行的单元格并设置其新值。
因此,似乎在某些情况下可能不需要 animation,因为单元格可能不在屏幕上或不需要,因此更改数据的最简单方法是在索引路径处获取单元格并在没有此 function 的情况下更改数据。
由于您在循环中运行它,您很可能在前一个 indexPath 的scrollToRow
完成之前启动下一个 indexPath 的reloadRows
,这可能会导致一些异常行为。
由于 UITableView 没有自己的完成处理程序,我们可以尝试使用带有递归的 CoreAnimation,这可以是选项 5。
这是我准备的小例子。 我的样本是这样的:
tableView.reloadRows(at:
tableView.scrollToRow(at:
这是我如何做到的
首先,我扩展 UITableView 以使用 CoreAnimation 块来执行reloadRows
和scrollToRow
extension UITableView
{
func reloadRows(at indexPaths: [IndexPath],
with animation: UITableView.RowAnimation,
completion: (() -> Void)?)
{
CATransaction.begin()
CATransaction.setCompletionBlock(completion)
reloadRows(at: indexPaths, with: animation)
CATransaction.commit()
}
func scrollToRow(at indexPath: IndexPath,
at scrollPosition: UITableView.ScrollPosition,
animated: Bool,
completion: (() -> Void)?)
{
CATransaction.begin()
CATransaction.setCompletionBlock(completion)
CATransaction.setAnimationDuration(2) // set what you want
scrollToRow(at: indexPath, at: scrollPosition, animated: animated)
CATransaction.commit()
}
}
以下是我如何在我的视图 controller 设置中使用此扩展
class TableViewAnimation: UITableViewController
{
let numberOfRows = 15
// Change the color of these rows in tableview
var colorChangeArray: [Int] = []
// Copy of colorChangeArray used in recursion
var colorChangeQueue: [Int] = []
// Change the color of row to this
private let colorToChange = UIColor.systemBlue
// Normal cell color
private let colorNormal = UIColor.gray
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = .white
setUpNavigationBar()
setUpTableView()
}
private func setUpNavigationBar()
{
title = "Table View Animate"
let barButton = UIBarButtonItem(title: "Animate",
style: .plain,
target: self,
action: #selector(didTapAnimateButton))
navigationItem.rightBarButtonItem = barButton
}
private func setUpTableView()
{
tableView.register(CustomCell.self,
forCellReuseIdentifier: CustomCell.identifier)
}
@objc
func didTapAnimateButton()
{
// Queue all the rows that should change
// We will dequeue these in the animation function
// and the recursive function stops when the queue
// is empty
colorChangeQueue = [1, 3, 6, 12]
resumeAnimation()
}
// Recursion function rather than loops using our
// custom functions from extension
private func resumeAnimation()
{
if !colorChangeQueue.isEmpty
{
let rowToChange = colorChangeQueue.removeFirst()
print("starting \(rowToChange) animation")
let indexPath = IndexPath(row: rowToChange,
section: 0)
colorChangeArray.append(rowToChange)
tableView.reloadRows(at: [indexPath],
with: .top) { [weak self] in
self?.tableView.scrollToRow(at: indexPath,
at: .top,
animated: true,
completion: {
// recursively call the function again with a small delay
DispatchQueue.main.asyncAfter(deadline: .now() + 1)
{
print("complete \(rowToChange) animation")
self?.resumeAnimation()
}
})
}
}
}
}
最后,这是数据源和委托,但这里没有发生任何独特的事情,只是为了完整性而添加它
extension TableViewAnimation
{
override func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int
{
return numberOfRows
}
override func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell
= tableView.dequeueReusableCell(withIdentifier: CustomCell.identifier) as! CustomCell
if colorChangeArray.contains(indexPath.row)
{
cell.mainView.backgroundColor = colorToChange
}
else
{
cell.mainView.backgroundColor = colorNormal
}
cell.textLabel?.textAlignment = .center
cell.textLabel?.text = "Row \(indexPath.row)"
return cell
}
override func tableView(_ tableView: UITableView,
heightForRowAt indexPath: IndexPath) -> CGFloat
{
return 150
}
}
现在似乎每一行的动画都正确排序了:
而且,如果您在控制台中看到打印,它是按顺序排列的,而循环方法不会发生:
starting 1 animation
complete 1 animation
starting 3 animation
complete 3 animation
starting 6 animation
complete 6 animation
starting 12 animation
complete 12 animation
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.