【发布时间】:2020-02-05 15:22:35
【问题描述】:
你好我的程序员朋友们,
我遇到了 swift 的 UITableView 的问题,我只是找不到错误。
我对 iOS 的 TableViews 非常熟悉,我知道他们如何使用队列来尽可能提高性能。
我通常只是在我的 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”,如前所述,我几乎所有的 TableView 都使用了它:
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 数组中的双重输入造成的。
感谢您的帮助!
【问题讨论】:
-
这似乎非常错误。通常,您会跟踪 数据 中的更改(如您所展示的
[Rating]数组)。然后,在cellForRowAt中,您将出列可重用单元格。我从未见过在其他地方创建单元格并尝试将它们保存在数组中的方法, -
dequeueReusableCell正在从您的表格视图中返回现有单元格,您将这些单元格添加回数组中,这就是您看到重复行的原因。我认为你需要回去看看如何正确地使单元格出队。 -
这种方法充满了问题。 Apple 提供了一种用于部署 tableViews 的机制 - 正如@JamesP 所说,您应该非常强烈地考虑使用它。
-
哦,好的,很高兴知道。我曾经只是想按照我的做法去做,并且在更简单的 tableViews 中效果很好,所以我从不认为它是错误的。
-
我会再看一下文档。从来没有想过在另一个地方出队一个可重用的单元格然后数据源可能是一个问题。谢谢大家!
标签: ios arrays swift uitableview queue