首页 文章

如何在Swift 4中点击单元格时可视化tableViewCell中的更改

提问于
浏览
3

我想制作tableView并在点击单元格后更改单元格中的文本并在一个函数内完成 . 在Swift的第一个版本中,它起作用,现在它在完成后才改变

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)

这是一个代码示例:

import UIKit

class TableViewController: UITableViewController {
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 10
    }

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

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let cell = tableView.cellForRow(at: indexPath)

        cell?.textLabel?.text = "hello"
        sleep(2)
        cell?.textLabel?.text = "bye"
        sleep(2)       
    }
}

我希望它像这样工作:点击单元格 - >单元格文本更改为“hello”,等待2秒,然后更改为“再见”,等待另外2秒并继续

但现在它的工作方式如下:点击单元格 - >等待4秒,更改为“再见”并继续

2 回答

  • 1

    您可以使用 DispatchQueue 来获得更好的结果:

    cell?.textLabel?.text = "hello"
      tableView.isUserInteractionEnabled = false
      DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
           // your code here
           cell?.textLabel?.text = "bye"
           tableView.isUserInteractionEnabled = true
        }
    
  • 1

    这实际上是一项比看起来更复杂的任务 .

    首先,永远不要在主队列上睡觉 . 这会锁定主线程并使您的应用看起来没有响应 .

    您需要有一个数据模型来跟踪每一行的 Headers ,在这种情况下,还需要一个知道何时更新行的计时器 .

    您还需要处理用户点击一行,然后在屏幕上向后滚动该行 .

    它还有助于允许用户点击多行并根据需要进行每次更新 . 并且您需要在行更新之间的延迟期间处理离开表视图的用户 .

    这是一个支持所有这些问题的解决方案 .

    class TableViewController: UITableViewController {
        struct RowData {
            var title: String
            var timer: Timer?
    
            init(_ title: String) {
                self.title = title
            }
        }
    
        var rowData = [RowData]()
    
        override func numberOfSections(in tableView: UITableView) -> Int {
            return 1
        }
    
        override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return rowData.count
        }
    
        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell") ?? UITableViewCell(style: .default, reuseIdentifier: "cell")
    
            let data = rowData[indexPath.row]
    
            cell.textLabel?.text = data.title
    
            return cell
        }
    
        override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
            var data = rowData[indexPath.row]
            if data.timer == nil {
                // No timer for this row - set to "hello" and start a timer
                let timer = Timer(timeInterval: 2, target: self, selector: #selector(timerTick), userInfo: indexPath, repeats: false)
                RunLoop.main.add(timer, forMode: .commonModes) // Allow timer to work while scrolling
                data.title = "hello"
                data.timer = timer
                rowData[indexPath.row] = data
    
                tableView.reloadRows(at: [ indexPath ], with: .fade)
            }
        }
    
        @objc func timerTick(_ timer: Timer) {
            // Update the row to "bye" and reset the timer
            let indexPath = timer.userInfo as! IndexPath
    
            var data = rowData[indexPath.row]
            data.timer = nil
            data.title = "bye"
            rowData[indexPath.row] = data
    
            tableView.reloadRows(at: [ indexPath ], with: .fade)
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // Load test data
            for i in 1...50 {
                rowData.append(RowData("Row \(i)"))
            }
        }
    
        override func viewWillDisappear(_ animated: Bool) {
            if isMovingFromParentViewController || isBeingDismissed {
                // Cancel all timers
                for data in rowData {
                    if let timer = data.timer {
                        timer.invalidate()
                    }
                }
            }
        }
    }
    

    通过一些更改,您还可以支持用户在达到“bye”值之前点击一行,并将行重置为原始值 . 这是一个练习 .

相关问题