ios - 快速计数停止在错误的数字
问题描述
目标是:计算自用户输入所需天数以来已经过去了多少天,例如用户输入 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),
])
}
}
解决方案
我会将运算符更改handleTimer()
为>=
from>
推荐阅读
- android - 重新启动应用程序后,单独的后台线程指向旧 ViewModel
- mysql - T3 Table 中的两个表列合并为一列
- bitbucket - 无法连接到 bitbucket 管道中的目录
- php - 引导程序在 symfony 模板中不起作用
- ansible - Ansible:致命:[test1]:失败!=> {"msg": "等待提权提示超时(62s):"}
- android-studio - 在垂直表面(墙壁)上添加带有文本的对象 - ARCore Android studio
- android - 当所需屏幕已经显示时,避免添加 FLAG_ACTIVITY_NEW_TASK
- python - 使用 Visual Studio 时设置 python 搜索路径
- angular - 带有 ASP.NET Core Web API 的 Angular:接收 [object, Object]
- arrays - 检查值的条件,并存储在 MongoDB 的新字段中