首页 > 解决方案 > 快速计数停止在错误的数字

问题描述

目标是:计算自用户输入所需天数以来已经过去了多少天,例如用户输入 3 天并开始计数(1、2、3 -> 停止)。

(我将天改为秒以检查逻辑。)

问题:我尝试了几种方法,但我总是遇到同样的问题:计时器在输入的天数处停止- 1(例如:输入了 3,2 是屏幕上的最后一个数字,但必须是 3!)

我哪里错了?

我的代码:


   import UIKit

class ViewController: UIViewController {

    private let mainLabel = UILabel.makeLabel(text: "Day number")
    private let startButton = UIButton.makeButton("Start", titleColor: .red, bgColor: .lightGray)
    private let stopButton = UIButton.makeButton("Stop", titleColor: .black, bgColor: .lightGray)
    private var startDate: Date?
    private var endDate: Date?
    private let startTimeKey = "StartTime"
    private let endTimeKey = "EndDate"
    private weak var timer: Timer?
    private let defaults = UserDefaults.standard

    let dateComponentsFormatter: DateComponentsFormatter = {
          let formatter = DateComponentsFormatter()
          formatter.allowedUnits = [.hour, .minute, .second]
          formatter.unitsStyle = .positional
          formatter.zeroFormattingBehavior = .pad
          return formatter
      }()

    override func viewDidLoad() {
        super.viewDidLoad()
        setupLayouts()
        endDate = defaults.value(forKey: endTimeKey) as? Date
        startDate = defaults.value(forKey: startTimeKey) as? Date
        if let endTime = endDate, let startTime = startDate {
            if endTime < Date() {
                startTimer(endTime: endTime, startTime: startTime)
            } else {
                timer?.invalidate()
            }
        }
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        startButton.addTarget(self, action: #selector(startButtonIsPressed), for: .touchUpInside)
        stopButton.addTarget(self, action: #selector(stopButtonIsPressed), for: .touchUpInside)
    }

    @objc func startButtonIsPressed() {
        let alert = UIAlertController(title: "Hello", message: "Enter number of days", preferredStyle: .alert)
        let ok = UIAlertAction(title: "OK", style: .default) { [unowned alert] _ in
            guard let daysNumber = alert.textFields?.first?.text, !daysNumber.isEmpty else { return }
            self.startDate = Date()
            self.defaults.set(self.startDate, forKey: self.startTimeKey)

            self.endDate = Calendar.current.date(byAdding: .second, value: Int(daysNumber)!, to: Date())
            self.defaults.set(self.endDate, forKey: "EndDate")

            if self.endDate! > self.startDate! {
                self.timer = nil
                self.startTimer(endTime: self.endDate!, startTime: self.startDate!)
            }
        }
        let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
        alert.addAction(ok)
        alert.addAction(cancel)
        alert.addTextField { (textField) in
            textField.placeholder = "Number"
            textField.keyboardType = .numberPad
        }
        present(alert, animated: true)
    }

    @objc func stopButtonIsPressed() {
        timer?.invalidate()
      }

 func startTimer(endTime: Date, startTime: Date) {

            defaults.set(endTime, forKey: endTimeKey)
            defaults.set(startTime, forKey: startTimeKey)
            self.endDate = endTime
            self.startDate = startTime

            timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(handleTimer), userInfo: nil, repeats: true)
        }
        @objc func handleTimer() {
            if endDate! > Date() {
                mainLabel.text = dateComponentsFormatter.string(from: startDate!, to: Date())
            } else {
             timer?.invalidate()
            }
        }

    func setupLayouts() {
        view.addSubview(mainLabel)
        view.addSubview(startButton)
        view.addSubview(stopButton)
        NSLayoutConstraint.activate([
            mainLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            mainLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            startButton.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -70),
            startButton.topAnchor.constraint(equalTo: mainLabel.bottomAnchor, constant: 140),
            stopButton.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 70),
            stopButton.topAnchor.constraint(equalTo: mainLabel.bottomAnchor, constant: 140),
        ])
    }
}

标签: iosswifttimer

解决方案


我会将运算符更改handleTimer()>=from>


推荐阅读