你好,我的程序员朋友们,
我遇到了swift的UITableView问题,但我找不到错误。
我对iOS的TableView非常熟悉,我知道它们如何使用队列来尽可能提高性能。
我通常只在ViewController中构建UITableViewCells数组,然后基于该数组更新TableView。通过这种技术,我可以对所有TableView使用一个DataSource类,这非常干净并且始终可以正常工作。
到现在:
这是我的第一个TableView,具有许多相同类型的单元格,如果用户按下最后一个单元格“ LoadMore”的单元格,则会向其中添加新的单元格。
但是问题是,如果按下“ LoadMore”单元格,则在TableView更新后,TableView甚至tableViewCells数组会自行重新排序,甚至包含无法正确显示的重复条目。
我找不到原因。一切正常,所有数据和tableViewCells数组绝对正确,直到调用TableViews reloadData()为止。我现在检查了很多次更新前后的内容。
这是我的ViewController的(精简版)代码,该代码仅包含TableView:
import UIKit
class UserDataTableViewController: UIViewController, UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!
//Auto updating TableView
var tableViewCells = [UITableViewCell]() {
didSet {
dataSource.update(with: tableViewCells)
tableView.reloadData()
tableView.beginUpdates()
tableView.endUpdates()
}
}
//DataSource for Table View
var dataSource = NormalTableDataSource(cells: nil)
override func viewDidLoad() {
super.viewDidLoad()
//TableView
tableView.dataSource = dataSource
tableView.delegate = self
tableView.separatorColor = .darkText
//get next data
nextData()
}
func nextData() {
if let data = self.data {
//some code that finds the next data and then calls:
addDataToTableView(data: nextData, morePages: true)
}
}
func addDataToTableView(data: Array<Any>, morePages: Bool = false) {
//create temp array out of old tableViewCells array
var tempCells = tableViewCells
//remove LoadMore cell if it exists
if (tempCells.count > 0) {
tempCells.removeLast()
}
//(Rating is a simple Struct)
if let ratings = data as? [Rating] {
//This loop runs aprox. 25 times
for rating in ratings {
let cell = tableView.dequeueReusableCell(withIdentifier: "UserRatedAlbumCell") as! UserRatedAlbumCell
cell.update(rating: rating)
tempCells.append(cell)
}
}
//add LoadMore cell
if (morePages) {
let loadMoreCell = tableView.dequeueReusableCell(withIdentifier: "LoadMoreCell")!
tempCells.append(loadMoreCell)
}
//update array, which automatically updates the tableView
self.tableViewCells = tempCells
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return tableViewCells[indexPath.row].frame.size.height
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableViewCells[indexPath.row]
if (cell.reuseIdentifier == "LoadMoreCell") {
self.nextData()
}
tableView.deselectRow(at: indexPath, animated: true)
}
}
这是“ UserRatedAlbumCell”类中的代码(也有所减少):
import UIKit
class UserRatedAlbumCell: UITableViewCell {
@IBOutlet weak var albumCoverImage: UIImageView!
@IBOutlet weak var albumNameLabel: UILabel!
//data
var album: Album?
var rating: Rating?
func update(rating: Rating) {
self.rating = rating
albumNameLabel.text = ""
albumCoverImage.image = nil
//---Some async task with completion block that returns "album":
{
if let album = album {
DispatchQueue.main.async {
self.update(album: album, rating: rating)
}
}
}
//---
}
func update(album: Album) {
self.album = album
albumNameLabel.text = album.attributes?.name
if let url = album.attributes?.artwork.url(forWidth: 150) {
albumCoverImage.downloaded(with: url)
}
}
}
这是我的“ NormalTableDataSource”,如前所述,几乎在我的所有TableViews中都使用了它:
import UIKit
class NormalTableDataSource: NSObject, UITableViewDataSource {
private var cells: [UITableViewCell]?
init(cells: [UITableViewCell]?) {
self.cells = cells
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cells?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cells = cells {
return cells[indexPath.row]
} else {
return UITableViewCell()
}
}
func update(with cells: [UITableViewCell]?) {
self.cells = cells
}
}
有谁知道为什么会这样吗?
如果需要,我可以提供TableView发生的屏幕截图。但是我可以告诉您,第一次按下LoadMore时,所有单元格都会重新排序,并且有很多空白单元格,这可能是由于tableViewCells数组中的两次输入引起的。
谢谢你的帮助!
最佳答案
长话短说dequeueReusableCell旨在从“ tableView(_ tableView:UITableView,cellForRowAt indexPath:IndexPath)”中调用,这就是您遇到问题的原因。
一个更复杂的故事是它返回表格视图本身认为不再使用的单元格,因为您将对这些单元格的引用存储在某个地方(例如tableViewCells属性)这一事实不会改变任何东西,表格视图仍然有权只要有意义,就重复使用这些单元。因此,每次调用nextData()时,都会得到重复的单元格。