简体   繁体   English

延迟出列可重用单元格

[英]Dequeue reusable cell with delay

I have a tableView where I insert 20 rows with delay using DispatchQueue method.我有一个 tableView,我使用 DispatchQueue 方法延迟插入 20 行。 First 10 rows appear fine.前 10 行看起来不错。 Problem starts with 11th one when Xcode begins to dequeue reusable rows.当 Xcode 开始使可重用行出列时,问题从第 11 个开始。 In simulator it looks like it starts to insert by 2 rows nearly at the same time (11th+12th, then 13th+14th).在模拟器中,它看起来几乎同时开始插入 2 行(第 11+12,然后第 13+14)。

I wonder why is that.我想知道为什么会这样。 Do DispatchQueue and tableView.dequeueReusableCell methods conflict? DispatchQueue 和 tableView.dequeueReusableCell 方法是否冲突? And if yes how to organize things properly?如果是的话,如何正确组织事情?

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)
            }
    }
}

Your code didn't work for me.你的代码对我不起作用。 May be you missed something to mention in your question.可能是您错过了问题中要提及的内容。 But with the information that I understood, I did some modification and now it runs (tested in iPhone X) as expected.但是根据我了解的信息,我做了一些修改,现在它可以按预期运行(在 iPhone X 中测试)。 Following is the working full source code.以下是工作的完整源代码。

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()
    }
}

I think using a Timer is the better solution in your use case:我认为在您的用例中使用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)
}

Try to place code inside DispatchQueue.main.asyncAfter in尝试将代码放在DispatchQueue.main.asyncAfter

self.tableView.beginUpdates()
self.tableView.endUpdates()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM