iOS 中 UITableView 每个单元格的时间倒计时



我想在表格视图的每个单元格上显示倒数计时器。

步骤

我有来自服务器的报价列表,有过期时间。所以在那之后,我想在 UITableView 上显示这个过期倒数计时器的每个单元格。

我正在做这样的事情。但没有结果。

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell =  tableView.dequeueReusableCell(withIdentifier: "cell") as! TimeCell
        cell.expiryTimeInterval = 2
        return cell

    }

**我的细胞类,我正在启动计时器。仅打印步骤 1 和步骤 2 **

class TimeCell: UITableViewCell {
    @IBOutlet weak var myLabel: UILabel!
    override func awakeFromNib() {
        super.awakeFromNib()
    }
    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }
    private var timer: Timer?
    private var timeCounter: Double = 0
    var expiryTimeInterval : TimeInterval? {
        didSet {
            startTimer()
            print("Step 1 (expiryTimeInterval!)")
        }
    }
    private func startTimer() {
   if let interval = expiryTimeInterval {
            timeCounter = interval
             print("Step 2 (interval)")
            if #available(iOS 10.0, *) {
                timer = Timer(timeInterval: 1.0,
                              repeats: true,
                              block: { [weak self] _ in
                                guard let strongSelf = self else {
                                    return
                                }
                                strongSelf.onComplete()
                })
            } else {
                timer = Timer(timeInterval: 1,
                              target: self,
                              selector: #selector(onComplete),
                              userInfo: nil,
                              repeats: true)
             }
        }
    }
    @objc func onComplete() {
        print("Step 3")
        guard timeCounter >= 0 else {
            timer?.invalidate()
            timer = nil
            return
        }
        myLabel.text = String(format: "%d", timeCounter)
        timeCounter -= 1
    }
}

我宁愿建议您创建一个自定义单元格,并在该单元格类中,根据来自服务器的值创建一个计时器。这样,每个单元格都有自己的计时器。这就是你可能想要的。在当前实现中,计时器处理程序不知道单元格或其行号。

class MyCustomCell: UITableViewCell {
    @IBOutlet weak private var myLabel: UILabel!
    private var timer: Timer?
    private var timeCounter: Double = 0
    var expiryTimeInterval: TimeInterval? {
        didSet {
            startTimer()
        }
    }
    private func startTimer() {
        if let interval = expiryTimeInterval {
            timeCounter = interval
            if #available(iOS 10.0, *) {
                timer = Timer(timeInterval: 1.0,
                              repeats: true,
                              block: { [weak self] _ in
                                guard let strongSelf = self else {
                                    return
                                }
                                strongSelf.onComplete()
                })
            } else {
                timer = Timer(timeInterval: 1.0,
                              target: self,
                              selector: #selector(onComplete),
                              userInfo: nil,
                              repeats: true)
            }
        }
    }
    @objc func onComplete() {
        guard timeCounter >= 0 else {
            timer?.invalidate()
            timer = nil
            return
        }
        myLabel.text = String(format: "%d", timeCounter)
        timeCounter -= 1
    }
}

用法

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell =  tableView.dequeueReusableCell(withIdentifier: "cell") as! MyCustomCell
    cell.expiryTimeInterval = 10
    return cell
}

转到单元格nibstoryboard,然后将TimeCell的类名更改为MyCustomCell

@Umair 阿米尔 我实现了您的解决方案,它工作正常,但是,接下来的代码行至关重要,因此每次滚动时都不会初始化计时器...

检查if timer == nil是不够的

override func prepareForReuse() {
    super.prepareForReuse()
    timer?.invalidate()
    timer = nil
}

您应该将其添加到单元格子类中。希望对您有所帮助!

    import UIKit
    class CompetitionTableViewCell: UITableViewCell {

        //MARK:- IBOutlets
        @IBOutlet weak var mainView: UIView!
        @IBOutlet weak var imageCompetition: UIImageView!
        @IBOutlet weak var btnStart: UIButton!
        @IBOutlet weak var lblTime: UILabel!
        @IBOutlet weak var lblCompititor: UILabel!
        @IBOutlet weak var lblPoints: UILabel!
        @IBOutlet weak var lblNameCompetition: UILabel!
        @IBOutlet weak var btnGoForTest: UIButton!

        //MARK:- Variable
        private var timer: Timer?
        private var timeCounter: Double = 0

        //MARK:- IBActions
        var expiryTimeInterval: TimeInterval? {
            didSet {
                if timer == nil
                {
                    startTimer()
                    RunLoop.current.add(timer!, forMode: .commonModes)
                }
            }
        }
        private func startTimer() {
            if let interval = expiryTimeInterval {
                timeCounter = interval
                if #available(iOS 10.0, *) {
                    timer = Timer(timeInterval: 1.0,
                                  repeats: true,
                                  block: { [weak self] _ in
                                    guard let strongSelf = self else {
                                        return
                                    }
                                    strongSelf.onComplete()
                    })
                } else {
                    timer = Timer(timeInterval: 1.0,
                                  target: self,
                                  selector: #selector(onComplete),
                                  userInfo: nil,
                                  repeats: true)
                }
            }
        }
        @objc func onComplete() {
            guard timeCounter >= 0 else {
                btnGoForTest.isUserInteractionEnabled = false
                lblTime.text = "Time ended."
                timer?.invalidate()
                timer = nil
                return
            }
            btnGoForTest.isUserInteractionEnabled = true
            let hours = Int(timeCounter) / 3600
            let minutes = Int(timeCounter) / 60 % 60
            let seconds = Int(timeCounter) % 60
            lblTime.text = String(format:"%02i:%02i:%02i", hours, minutes, seconds)
            timeCounter -= 1
            print("(timeCounter)")
        }

        override func awakeFromNib() {
            super.awakeFromNib()
             btnStart.setCornerRadiusForBtn()
        }
        override func setSelected(_ selected: Bool, animated: Bool) {
            super.setSelected(selected, animated: animated)

        }
        override func prepareForReuse() {
            super.prepareForReuse()
            timer?.invalidate()
            timer = nil
        }
    }

/***** code for your listing tableview ***************/
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

         let cell =  tableView.dequeueReusableCell(withIdentifier: "CompetitionTableViewCell") as! CompetitionTableViewCell

        cell.btnGoForTest.tag = indexPath.row
        cell.lblTime.tag = indexPath.row

        //cell.lblTime.tag = indexPath.row
        let dicttemp : Dictionary = arrAllCoursesList[indexPath.row] as! Dictionary<String,Any>
        if let getTime = dicttemp["endtime"] as? Int
        {
            cell.lblTime.text = ""
            let getTime1 : Double = Double(getTime)
            cell.expiryTimeInterval = getTime1


        }

        return cell
    }

最新更新