Несколько таймеров в UITableViewCell (Swift)


У меня есть UITableViewcells, которые создаются в разные моменты времени, и я хотел бы, чтобы каждый из них имел независимый таймер, который срабатывает, когда объект добавляется с reloadData()

Это то, что я сделал до сих пор

import UIKit

var timer = Timer()
var blinkStatus:Bool! = false
var time = 300


class LiveViewCell: UITableViewCell {

    let str = String(format:"%02d:%02d", (time / 60), (time % 100))
    func processTimer() {

        if time > 0 {
            time -= 1
            timeRemainingLbl.text = String(time)
        } else if time == 0 {
            timer.invalidate()
            timeRemainingLbl.text = "Due!"
            timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(LiveViewCell.blinkTimer), userInfo: nil, repeats: true)

        }

    }

    func blinkTimer() {
        if blinkStatus == false {
            timeRemainingLbl.textColor = UIColor(red:1.00, green:0.00, blue:0.00, alpha:1.0)
            blinkStatus = true
        } else if blinkStatus == true {
            timeRemainingLbl.textColor = UIColor.clear
            blinkStatus = false
        }

    }


    @IBOutlet weak var tableNumberLeftLabel: UILabel!
    @IBOutlet weak var guestNumbersLabel: UILabel!

    @IBOutlet weak var timeInTableLabel: UILabel!
    @IBOutlet weak var tableNumberLbl: UILabel!
    @IBOutlet weak var timeRemainingLbl: UILabel!


    var table: Table!


    func configureLiveCell(_ NT: Table) {

        layer.cornerRadius = 20
        timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(LiveViewCell.processTimer), userInfo: nil, repeats: true)
        tableNumberLbl.text = "T" + String(NT.number)
        timeRemainingLbl.text = String(time)

    }
}

Проблема возникает, когда configureLiveCell вызывается всякий раз, когда я создаю новую ячейку. Таймер, кажется, ускоряется, и я хотел бы, чтобы каждый таймер был независимым.

2 4

2 ответа:

Переопределите метод prepareForReuse.

override func prepareForReuse() {
    super.prepareForReuse()

    timer.invalidate()
}

Это будет вызвано непосредственно перед возвращением ячейки для использования другой строкой. Делая недействительным таймер здесь, Ваш configureLiveCell не создает еще один таймер.

Кстати-вы также должны добавить метод deinit и сделать недействительным таймер там тоже.

Вы также делаете СВОЙСТВО timer необязательным и устанавливаете его в nil после того, как вы его аннулируете. И, конечно, вам нужно добавить соответствующие проверки, чтобы иметь дело с тем, что это необязательно.

И один последнее изменение, которое вы должны сделать, это изменить timer, time, и blinkStatus таким образом, они являются переменными экземпляра, перемещая их внутри класса.

Вот код для управления таймером в ячейке UITableview в swift 2.0

IN ViewController

class ViewController: UIViewController, UITableViewDelegate , UITableViewDataSource{

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 5
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("TblCell", forIndexPath: indexPath) as! TblCell

        cell.selectionStyle = .None
        return cell
    }

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        let cell : TblCell = (tableView.cellForRowAtIndexPath(indexPath) as? TblCell)!
        cell.setupTimer(with: indexPath.row)
    }
}

В UITableviewCell

class TblCell: UITableViewCell {
    @IBOutlet weak var lblTimer: UILabel!

    var couponTimer : NSTimer?
    var startTime : NSDate!
    var currentIndex : Int = 1

    func setupTimer(`with` indexPath: Int){
        currentIndex = indexPath + 1

        self.startTime = NSDate()

        if self.couponTimer != nil {
            self.couponTimer?.invalidate()
            self.couponTimer = nil
        }

        couponTimer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(self.calculateTime), userInfo: nil, repeats: true);

        NSRunLoop.currentRunLoop().addTimer(couponTimer!, forMode: NSRunLoopCommonModes)
        couponTimer?.fire()
    }

    func stopTimer(){
        if self.couponTimer != nil {
            self.couponTimer?.invalidate()
            self.couponTimer = nil
        }
    }

    func calculateTime() {
        let dateFormatter = NSDateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"

        let dateFormatter1 = NSDateFormatter()
        dateFormatter1.dateFormat = "yyyy-MM-dd"

        let tomorrow = NSCalendar.currentCalendar()
            .dateByAddingUnit(
                .Day,
                value: currentIndex,
                toDate: NSDate(),
                options: []
        )

        let tomorrowDate = dateFormatter1.stringFromDate(tomorrow!)
        let tomorrowActiveDate = dateFormatter.dateFromString(tomorrowDate + " " + "10:15:00")

        let currentDate   = NSDate()

        let strTimer : String = tomorrowActiveDate!.offsetFrom(currentDate)
        self.lblTimer.text = strTimer
        self.lblTimer.textColor = UIColor.whiteColor()
        self.lblTimer.backgroundColor = UIColor(red: 255.0/255.0, green: 44.0/255.0, blue: 86.0/255.0, alpha: 1.0)
    }
}

Расширение

extension NSDate {

    func offsetFrom(date:NSDate) -> String {

        let dayHourMinuteSecond: NSCalendarUnit = [.Day, .Hour, .Minute, .Second]
        let difference = NSCalendar.currentCalendar().components(dayHourMinuteSecond, fromDate: date, toDate: self, options: [])

        var seconds : String = ""
        var minutes : String = ""
        var hours : String = ""
        var days : String = ""

        let tmp1 : String = String(format: "%.2d", difference.second)
        let tmp2 : String = String(format: "%.2d", difference.minute)
        let tmp3 : String = String(format: "%.2d", difference.hour)
        let tmp4 : String = String(format: "%d", difference.day)

        seconds = "\(tmp1)"
        minutes = "\(tmp2)" + ":" + seconds
        hours = "\(tmp3)" + ":" + minutes
        days = "\(tmp4)d" + " " + hours

        if difference.second >= 0 && difference.minute >= 0 && difference.hour >= 0 && difference.day >= 0 {
            return days
        }
        else {
            return ""
        }
    }
}