你好,我的程序员朋友们,

我遇到了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()时,都会得到重复的单元格。

09-26 02:53