延迟使可重用单元出队

时间:2019-09-30 05:29:41

标签: ios swift uitableview grand-central-dispatch

我有一个tableView,其中使用DispatchQueue方法延迟插入20行。前10行看起来不错。当Xcode开始使可重复使用的行出队时,问题从第11个开始。在模拟器中,看起来几乎同时开始插入两行(第11 + 12,然后第13 + 14)。

我想知道为什么会这样。 DispatchQueue和tableView.dequeueReusableCell方法是否冲突?如果是的话,如何正确组织事情?

var numberOfCells = 0

//My TableView
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "TextCell")! as UITableViewCell
    return cell
}

//Function that inserts rows
func updateTableView(nextPassageID: Int) {
    for i in 0...numberOfCells - 1 {
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(i)) {
            self.numberOfCells += 1
            let indexPath = IndexPath(row: i, section: 0)
            self.tableView.insertRows(at: [indexPath], with: .fade)
            }
    }
}

3 个答案:

答案 0 :(得分:1)

您的代码对我不起作用。可能是您错过了问题中要提及的内容。但是根据我所了解的信息,我做了一些修改,现在可以按预期运行(在iPhone X中测试)。以下是有效的完整源代码。

import UIKit

class InsertCellViewController: UIViewController, UITableViewDataSource {

    var dataArray:Array<String> = []
    let reusableCellId = "AnimationCellId"
    var timer = Timer()
    var index = -1

    @IBOutlet weak var tableView: UITableView!

//    UIViewController lifecycle

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.register(UITableViewCell.self, forCellReuseIdentifier: reusableCellId)
        tableView.separatorStyle = .none
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        updateTableView()
    }

//     MARK : UITableViewDataSource

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dataArray.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: reusableCellId)!
        cell.textLabel?.text = dataArray[indexPath.row]

        return cell
    }

//    Supportive methods

    func updateTableView() {
        timer = Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(updateCounting), userInfo: nil, repeats: true)
    }

    @objc func updateCounting(){

        if index == 19 {
            timer.invalidate()
        }

        index += 1
        let indexPath = IndexPath(row: index, section: 0)

        self.tableView.beginUpdates()
        self.dataArray.append(String(index))
        self.tableView.insertRows(at: [indexPath], with: .fade)
        self.tableView.endUpdates()
    }
}

答案 1 :(得分:1)

我认为在您的用例中使用Timer是更好的解决方案:

private var cellCount = 0

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return cellCount
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
    cell.textLabel?.text = "Cell \(indexPath.row)"
    return cell
}

func addCells(count: Int) {
    guard count > 0 else { return }

    var alreadyAdded = 0
    Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] t in
        guard let self = self else {
            t.invalidate()
            return
        }

        self.cellCount += 1

        let indexPath = IndexPath(row: self.cellCount - 1, section: 0)
        self.tableView.insertRows(at: [indexPath], with: .fade)

        alreadyAdded += 1
        if alreadyAdded == count {
            t.invalidate()
        }
    }
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    addCells(count: 20)
}

答案 2 :(得分:0)

尝试将代码放在

DispatchQueue.main.asyncAfter
self.tableView.beginUpdates()
self.tableView.endUpdates()