Dequeue многоразовая ячейка с задержкой - PullRequest
0 голосов
/ 30 сентября 2019

У меня есть tableView, где я вставляю 20 строк с задержкой, используя метод DispatchQueue. Первые 10 строк выглядят хорошо. Проблема начинается с 11-го, когда Xcode начинает вытеснять повторно используемые строки. В симуляторе это выглядит так, как будто он начинает вставлять по 2 строки почти одновременно (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 ]

1 голос
/ 30 сентября 2019

Ваш код не работает для меня. Может быть, вы пропустили что-то, чтобы упомянуть в своем вопросе. Но с информацией, которую я понял, я сделал некоторую модификацию, и теперь она работает (проверено в 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 голос
/ 30 сентября 2019

Я думаю, что использование 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)
}
0 голосов
/ 30 сентября 2019

Попробуйте разместить код внутри DispatchQueue.main.asyncAfter в

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