Это на самом деле более сложная задача, чем кажется.
Прежде всего, никогда не спите в главной очереди. Это блокирует основной поток и приводит к тому, что ваше приложение перестает отвечать на запросы.
Вам нужна модель данных для отслеживания заголовка для каждой строки и, в этом случае, таймер, который так известен, когда нужно обновить строку.
Вам также нужно иметь дело с пользователем, который нажимает на строку, а затем прокручивает эту строку за пределы экрана и обратно.
Это также поможет пользователю нажать несколько строк и получать каждое обновление по мере необходимости. И вам нужно иметь дело с пользователем, покидающим табличное представление во время задержки между обновлениями строк.
Вот одно решение, которое поддерживает все эти проблемы.
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()
}
}
}
}
}
С некоторыми изменениями вы также можете поддержать пользователя, нажав строку до того, как она достигнет значения "пока", и вернуть строку к исходному значению. Это оставлено как упражнение.