ios - example - uitableview swift 4
Un temporizador por celda de vista de tabla (1)
Así es como lo haría:
- Cree una estructura para representar cada fila que contenga una hora de inicio y si esa fila se está ejecutando actualmente
-
Programe un temporizador repetitivo durante 0.5 segundos para tener en cuenta la fluctuación en
Timer
- Cada vez que se active el temporizador, actualice las filas visibles que tienen temporizadores "en ejecución"
import UIKit
struct TimerModel {
private var startTime: Date?
private var offset: TimeInterval = 0
var elapsed : TimeInterval {
get {
return self.elapsed(since:Date())
}
}
var isRunning = false {
didSet {
if isRunning {
self.startTime = Date()
} else {
if self.startTime != nil{
self.offset = self.elapsed
self.startTime = nil
}
}
}
}
func elapsed(since: Date) -> TimeInterval {
var elapsed = offset
if let startTime = self.startTime {
elapsed += -startTime.timeIntervalSince(since)
}
return elapsed
}
}
class ViewController: UIViewController {
@IBOutlet weak var tableview: UITableView!
var timer: Timer?
var timersActive = 0
let formatter: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.zeroFormattingBehavior = .pad
formatter.allowedUnits = [.hour, .minute, .second]
return formatter
}()
var timers = [TimerModel](repeating:TimerModel(), count:30)
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func elapsedTimeSince(_ startTime: Date) -> String {
let elapsed = -startTime.timeIntervalSinceNow
return self.formatter.string(from: elapsed) ?? "0:00:00"
}
func startTimer() {
self.timersActive += 1
guard self.timer == nil else {
return
}
self.timer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true, block: { [weak self] (timer) in
if let me = self {
for indexPath in me.tableview.indexPathsForVisibleRows ?? [] {
let timer = me.timers[indexPath.row]
if timer.isRunning {
if let cell = me.tableview.cellForRow(at: indexPath) {
cell.textLabel?.text = me.formatter.string(from: timer.elapsed) ?? "0:00:00"
}
}
}
}
})
}
func stopTimer() {
self.timersActive -= 1
if self.timersActive == 0 {
self.timer?.invalidate()
self.timer = nil
}
}
}
extension ViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.timers.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
let timer = self.timers[indexPath.row]
cell.imageView?.image = timer.isRunning ? #imageLiteral(resourceName: "GreenDot") : #imageLiteral(resourceName: "RedDot")
cell.textLabel?.text = self.formatter.string(from: timer.elapsed) ?? "0:00:00"
return cell
}
}
extension ViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.timers[indexPath.row].isRunning = !self.timers[indexPath.row].isRunning
self.tableview.reloadRows(at: [indexPath], with: .none)
if self.timers[indexPath.row].isRunning {
self.startTimer()
} else {
self.stopTimer()
}
}
}
Quiero tocar en la celda de la mesa e iniciar un temporizador. Cada celda debe tener su propio temporizador. He logrado configurar el temporizador, pero no de forma independiente, cuando configuro uno, todas las celdas están configuradas.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let currentCell = tableView.cellForRow(at: indexPath) as! StaffTableViewCell
if isRunning == false {
currentCell.cellImageView.image = UIImage(data: UIImagePNGRepresentation(#imageLiteral(resourceName: "greendot"))!)
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
counter += 1
let hourPortion = String(format: "%02d", counter / 3600)
let minutesPortion = String(format: "%02d", counter / 60)
let secondsPortion = String(format: "%02d", counter % 60)
//print("/(hourPortion):/(minutesPortion):/(secondsPortion)")
timeTotal = "/(hourPortion):/(minutesPortion):/(secondsPortion)"
currentCell.timerLabel.text = timeTotal
isRunning = true
}
}
tableView.reloadData()
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
timer.invalidate()
isRunning = false
let currentCell = tableView.cellForRow(at: indexPath) as! StaffTableViewCell
if let data = UIImagePNGRepresentation(#imageLiteral(resourceName: "reddot")) {
currentCell.cellImageView.image = UIImage(data: data)
}
tableView.reloadData()
}