我正在tableview单元格的类中创建一个计时器,并使用计时器每秒更新一个标签。但是对于某些单元格而言,标签正在每秒更新多次,而对于其他单元格则以不同的速率进行更新。我认为细胞的可重复性可能会导致问题。
我正在将计时器对象创建为实例变量:
var timer: Timer!
并致电:
runTimer(). //called in awakefromnib
而runtimer方法是:
func runTimer() {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(updateTimer)), userInfo: nil, repeats: true)
}
func updateTimer() {
seconds -= 1
timerLabel.text = timeString(time: seconds)
}
创建计时器的正确方法是什么,根据单元格中的某些登录情况,每个单元格每秒更新一次UILabel
?
编辑: 如果我的cellforrowAt:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Doubts Cell", for: indexPath) as! DoubtsTableViewCell
cell.postedQuestionAndAnswer = postedQuestionsArray[indexPath.row]
if cell.timer != nil {
cell.timer.invalidate()
}
cell.runTimer()
return cell
}
这是我所需的单元格的类代码:
var postedQuestionAndAnswer: PostedQuestionAndAnswer! {
didSet {
configureTableViewData()
}
}
override func awakeFromNib() {
super.awakeFromNib()
}
func configureTableViewData() {
//.....other code
seconds = getTimeRemaining(queryPostedTime: Double(postedQuestionAndAnswer.question!.createdAt), queryPostedDate: Double(postedQuestionAndAnswer.question!.createdAt))
}
func runTimer() {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(updateTimer)), userInfo: nil, repeats: true)
}
func updateTimer() {
seconds -= 1
timerLabel.text = timeString(time: seconds) //timestring returns desired formatted string
}
答案 0 :(得分:0)
如果我理解正确你只需要一个计时器。将其移动到viewController。在updateTimer()中只调用tableView.reloadData(),一次更新所有单元格。在你的单元格中,将timerLabel.text = timeString(time:seconds)添加到configureTableViewData()的末尾,并删除与计时器相关的所有内容。
这样所有单元格每秒都会更新,并且将为每个单元格调用configureTableViewData()以相应地更新标签。
答案 1 :(得分:0)
相反,有1个计时器,只是重新加载你的tableview,你的tableViewCell不应该有任何自定义逻辑,而是他们的父级抽象。
示例:
class TableViewController: UITableViewController {
var timer: Timer
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
runTimer()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
timer.invalidate()
}
func runTimer() {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(updateTimer)), userInfo: nil, repeats: true)
}
func updateTimer() {
self.tableView.reloadData()
}
func getTimeIntervalForTableViewCell() -> TimeInterval { // Not sure what the 'seconds' object type is meant to be so I just used TimeInterval
seconds = getTimeRemaining(queryPostedTime: Double(postedQuestionAndAnswer.question!.createdAt),
queryPostedDate: Double(postedQuestionAndAnswer.question!.createdAt))
return seconds
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Doubts Cell", for: indexPath) as! DoubtsTableViewCell
// rest of your databinding logic here
let timeInterval = self.getTimeIntervalForTableViewCell()
cell.timerLabel.text = timeString(time: timeInterval)
return cell
}
}
答案 2 :(得分:0)
最好在viewController中创建一个包含struct
和秒Timer
的数组,例如:
struct MyTimer {
var timer: Timer?
var seconds: Int
init (seconds: Int) {
self.seconds = seconds
}
}
这样声明:
var timers = [[MyTimer(seconds: 5), MyTimer(seconds: 6)],
[MyTimer(seconds: 3), MyTimer(seconds: 4), MyTimer(seconds: 3), MyTimer(seconds: 4), MyTimer(seconds: 3), MyTimer(seconds: 4), MyTimer(seconds: 3), MyTimer(seconds: 4), MyTimer(seconds: 3), MyTimer(seconds: 4), MyTimer(seconds: 3), MyTimer(seconds: 4), MyTimer(seconds: 3), MyTimer(seconds: 4), MyTimer(seconds: 3), MyTimer(seconds: 4), MyTimer(seconds: 3), MyTimer(seconds: 4), MyTimer(seconds: 3), MyTimer(seconds: 4)]]
然后,每当它还不存在时,您将需要创建计时器。
func cellForRow(at indexPath: IndexPath) -> UITableViewCell? {
if self.timers[indexPath.section][indexPath.row].timer == nil {
self.timers[indexPath.section][indexPath.row].timer = self.createTimer(indexPath: indexPath)
}
// retrieve your cell here
cell.timerLabel.text = String(self.timers[indexPath.section][indexPath.row].seconds)
return cell
}
创建计时器可能就像:
func createTimer (indexPath: IndexPath) -> Timer {
let timeInterVal = self.getTimeInterval(indexPath: indexPath)
let timer = Timer.scheduledTimer(timeInterval: timeInterVal,
target: self,
selector: #selector(updateTimer(sender:)),
userInfo: ["indexPath": indexPath],
repeats: true)
return timer
}
func getTimeInterval (indexPath: IndexPath) -> TimeInterval {
return 1 // or return a value depending on the indexPath
}
然后,更新计时器:
@objc func updateTimer (sender: Timer) {
guard
let userInfo = sender.userInfo as? [String: IndexPath],
let idx = userInfo["indexPath"] else {
return
}
self.timers[idx.section][idx.row].seconds = self.timers[idx.section][idx.row].seconds - 1
if
let indexPathes = self.tableView.indexPathsForVisibleRows,
indexPathes.contains(idx) {
self.tableView.reloadRows(at: [idx], with: .none) // update directly the cell if it's visible
}
}