Sample program using timers to update the rows in TableView

It has to do the following:

  1. Ability to stop and start the timers on individual rows.
  2. Store the values of the rows when it goes out of display.
//
//  RobinHoodTableViewController.swift
//  TimerSwift
//
//  Created by darshan on 11/29/22.
//

import UIKit

class RobinHoodTableViewController: UITableViewController {
    static var symbols = ["BNB", "BTC", "USDC", "ETH", "ETC", "LTC", "LINK", "ALGO", "DOT", "USDT", "DAI", "EOS", "TRX", "LINK", "BNB", "BTC", "USDC", "ETH", "ETC", "LTC", "LINK", "BNB", "BTC", "USDC", "ETH", "ETC", "LTC", "LINK", "BNB", "BTC", "USDC", "ETH", "ETC", "LTC", "LINK"]
    static var stopArray : [Bool] = []
    static var array : [Float] = []
    static func initializeArray(rows: Int) {
        for _ in 0...rows-1 {
            RobinHoodTableViewController.array.append(0)
            RobinHoodTableViewController.stopArray.append(false)
        }
    }
    
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return RobinHoodTableViewController.symbols.count
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let tableviewCell = UITableViewCell(style: .subtitle, reuseIdentifier: "Seconds")
        tableviewCell.textLabel?.text = String(format: "%.2f", RobinHoodTableViewController.array[indexPath.row])
        tableviewCell.detailTextLabel?.text = RobinHoodTableViewController.symbols[indexPath.row]
        return tableviewCell
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Seconds")
        RobinHoodTableViewController.initializeArray(rows: 50)
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        self .startTimerForVisibleItems()
    }
    
    func startTimerForVisibleItems() {
        let visibleRows = tableView.indexPathsForVisibleRows
        for indexpath in visibleRows ?? [] {
            self.startTimerForRow(row: indexpath.row)
        }
    }
    
    @objc func fireTimer(timer: Timer) {
        guard let context = timer.userInfo as? [String: Int] else { return }
        let firedRow = context["row", default: 0]
        var valueFromArray = RobinHoodTableViewController.array[firedRow]
        valueFromArray += 0.1
        RobinHoodTableViewController.array[firedRow] = valueFromArray
        let cell = tableView.cellForRow(at: IndexPath(row: firedRow, section: 0))
        cell?.textLabel?.text = String(format: "%.2f", valueFromArray)
        if(!(tableView.indexPathsForVisibleRows?.contains(IndexPath(row: firedRow, section: 0)) ?? false)) {
            timer.invalidate()
        }
        if(RobinHoodTableViewController.stopArray[firedRow] == true) {
            timer.invalidate()
        }
    }
    
    override func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        self .startTimerForVisibleItems()
    }
    
    func startTimerForRow(row: Int) {
        let context = ["row": row]
        Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(fireTimer), userInfo: context, repeats: true)
    }
    
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if(RobinHoodTableViewController.stopArray[indexPath.row] == true) {
            RobinHoodTableViewController.stopArray[indexPath.row] = false
            self.startTimerForRow(row: indexPath.row)
        } else {
            RobinHoodTableViewController.stopArray[indexPath.row] = true
        }
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *