【问题标题】:Dequeue reusable cell with delay延迟出列可重用单元
【发布时间】:2019-09-30 05:29:41
【问题描述】:

我有一个 tableView,我使用 DispatchQueue 方法延迟插入 20 行。前 10 行看起来不错。当 Xcode 开始将可重用行出列时,问题从第 11 个开始。在模拟器中,它看起来几乎同时开始插入 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)
            }
    }
}

【问题讨论】:

    标签: ios swift uitableview grand-central-dispatch


    【解决方案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】:

      您的代码对我不起作用。可能是您错过了问题中要提及的内容。但是根据我理解的信息,我做了一些修改,现在它可以按预期运行(在 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()
          }
      }
      

      【讨论】:

        【解决方案3】:

        尝试将代码放在DispatchQueue.main.asyncAfter

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

        【讨论】:

        • 并没有真正改变任何东西。据我所知,当您想要对 tableView 进行多项更改时,您会使用 beginUpdates() 和 endUpdates()。不过还是谢谢你!
        猜你喜欢
        • 2019-09-16
        • 2023-04-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-01
        • 2019-03-01
        • 1970-01-01
        • 2015-06-21
        • 2018-11-22
        相关资源
        最近更新 更多