Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 更新TableView后,TableViewCells数组会重新排序自身_Ios_Arrays_Swift_Uitableview_Queue - Fatal编程技术网

Ios 更新TableView后,TableViewCells数组会重新排序自身

Ios 更新TableView后,TableViewCells数组会重新排序自身,ios,arrays,swift,uitableview,queue,Ios,Arrays,Swift,Uitableview,Queue,你好,我的程序员朋友们, 我遇到了swift的UITableView的问题,我就是找不到错误 我对iOS的TableView感到非常厌倦,我知道他们如何尽可能高效地使用队列 我通常只是在我的ViewController中构建一个UITableViewCells数组,并基于该数组更新TableView。使用这种技术,我可以为我的所有TableView使用一个DataSource类,这是非常干净的,并且总是工作得很好 到目前为止: 这是我的第一个具有许多相同类型单元格的TableView,如果用户按

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

我遇到了swift的UITableView的问题,我就是找不到错误

我对iOS的TableView感到非常厌倦,我知道他们如何尽可能高效地使用队列

我通常只是在我的ViewController中构建一个UITableViewCells数组,并基于该数组更新TableView。使用这种技术,我可以为我的所有TableView使用一个DataSource类,这是非常干净的,并且总是工作得很好

到目前为止: 这是我的第一个具有许多相同类型单元格的TableView,如果用户按下最后一个单元格“LoadMore”单元格,我会向其中添加新单元格。 但问题是,如果按下“LoadMore”单元格,一旦TableView更新,TableView甚至tableViewCells数组都会重新排序,甚至包含无法正确显示的双条目

我找不到原因。在调用TableViews reloadData()之前,一切正常,所有数据和tableViewCells数组都是正确的。我现在多次检查更新前后它们包含的内容

以下是我的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)
    }
}
这是我的“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数组中的双条目造成的


谢谢你的帮助

长话短说的dequeueReusableCell是从“tableView(\uTableView:UITableView,cellForRowAt indexPath:indexPath)”调用的,这就是您遇到问题的原因


一个更详细的故事是,它返回表视图本身认为不再使用的单元格,您将对这些单元格的引用存储在某个位置(如tableViewCells属性)这一事实不会改变任何事情,表视图仍然有权在对其有意义时重用这些单元格。因此,每次调用nextData()都会得到重复的单元格。

这似乎是非常错误的。通常,您可以跟踪数据中的更改(如图所示的
[Rating]
数组)。然后,在
cellForRowAt
中,您将对可重用单元进行出列。我从未见过在其他地方创建单元格并尝试将其保存在数组中的方法,
dequeueReusableCell
从您的tableview返回现有单元格,您正在将其添加回数组中,这就是为什么您会看到重复的行。我认为您需要回头看看如何正确地将单元格出列。这种方法充满了问题。Apple提供了一种部署桌面视图的机制——正如JamesP所说的,你应该非常慎重地考虑使用它。哦,好的,很高兴知道。我曾经有过这样做的想法,它在更简单的表视图中运行良好,因此我从未认为它有问题。我将再次查看文档。从来没有想过在另一个地方对可重用单元进行排队,那么数据源可能是一个问题。谢谢大家!哦,好吧,我不知道。谢谢
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
    }
}