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

时间:2018-05-07 20:14:04

标签: ios swift uitableview

我想创建tableView并在点击单元格后更改单元格中的文本并在一个函数内执行。在Swift的第一个版本中,它起作用了,现在只是在完成后改变了

覆盖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秒,然后更改为“bye”,等待另外2秒并继续

但现在它的工作原理如下: 点按小区 - >等待4秒,改为“再见”并继续

2 个答案:

答案 0 :(得分: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 :(得分:1)

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

首先,永远不要在主队列上睡觉。这会锁定主线程并使您的应用显示无响应。

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

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

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

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

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”值之前点击一行并将行重置为原始值。这是一个练习。