Как визуализировать изменения в tableViewCell при нажатии на ячейку в Swift 4 - PullRequest
0 голосов
/ 07 мая 2018

Я хочу сделать tableView и после нажатия на ячейку, чтобы изменить текст в ячейке и сделать это внутри одной функции. В одной из первых версий Swift это работало, и теперь оно просто изменилось после окончания

переопределить функцию 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)       
    }
}

Я хочу, чтобы это работало так: нажмите на ячейку -> текст ячейки изменился на «привет», ждет 2 секунды, затем изменился на «пока», ждет еще 2 секунды и продолжает

Но теперь это работает так: нажмите на ячейку -> ждет 4 секунды, меняется на «пока» и продолжается

Ответы [ 2 ]

0 голосов
/ 08 мая 2018

Это на самом деле более сложная задача, чем кажется.

Прежде всего, никогда не спите в главной очереди. Это блокирует основной поток и приводит к тому, что ваше приложение перестает отвечать на запросы.

Вам нужна модель данных для отслеживания заголовка для каждой строки и, в этом случае, таймер, который так известен, когда нужно обновить строку.

Вам также нужно иметь дело с пользователем, который нажимает на строку, а затем прокручивает эту строку за пределы экрана и обратно.

Это также поможет пользователю нажать несколько строк и получать каждое обновление по мере необходимости. И вам нужно иметь дело с пользователем, покидающим табличное представление во время задержки между обновлениями строк.

Вот одно решение, которое поддерживает все эти проблемы.

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

С некоторыми изменениями вы также можете поддержать пользователя, нажав строку до того, как она достигнет значения "пока", и вернуть строку к исходному значению. Это оставлено как упражнение.

0 голосов
/ 07 мая 2018

Вы можете использовать DispatchQueue, чтобы получить лучший результат:

  cell?.textLabel?.text = "hello"
  tableView.isUserInteractionEnabled = false
  DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
       // your code here
       cell?.textLabel?.text = "bye"
       tableView.isUserInteractionEnabled = true
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...