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

时间:2018-01-12 07:54:18

标签: ios swift uitableview

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

步骤

我有来自服务器的优惠清单,有过期时间。所以在那之后我想用UITableView上的每个单元显示这个过期倒数计时器。

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

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell =  tableView.dequeueReusableCell(withIdentifier: "cell") as! TimeCell
        cell.expiryTimeInterval = 2

        return cell



    }

**我的Cell Class,我正在启动计时器。印刷Step1&仅限步骤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
    }

}

3 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:1)

@Umair Aamir我实施了您的解决方案,并且它正常工作,但是,下一行代码至关重要,因此每次滚动时都不会初始化计时器...

仅仅检查if timer == nil

是不够的
override func prepareForReuse() {
    super.prepareForReuse()

    timer?.invalidate()
    timer = nil
}

您应该在您的单元格子类中添加它。 希望它有所帮助!

答案 2 :(得分:-1)

    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

    }