[英]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.