gpt4 book ai didi

swift - 在 Swift 中以定义的时间停止计时器

转载 作者:行者123 更新时间:2023-11-28 05:57:27 28 4
gpt4 key购买 nike

我正在尝试构建一个秒表,例如,它将计数到 3.0 秒,停止,然后允许我使用新的背景/标签覆盖应用程序的 View 。我的问题是我找不到让计时器在 3 秒时自行停止和暂停的方法 - 每当我编写语句时,它只会继续计数而不做任何事情。我应该将语句放在这段代码中的什么位置,我将如何编写它?

import UIKit

class ViewController: UIViewController {
var time = 0.0
var timer = Timer()

@IBOutlet weak var lbl: UILabel!

@IBAction func start(_ sender: UIButton)
{
timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(ViewController.action), userInfo: nil, repeats: false)
}

@IBAction func pause(_ sender: UIButton)
{
timer.invalidate()
}

@IBAction func reset(_ sender: UIButton)
{
timer.invalidate()
time = 0.0
lbl.text = ("0")
}

@objc func action()
{
time += 0.1
lbl.text = String(time)
}
}

最佳答案

首先分离您的期望。

“时钟”是从开始到现在的时间段的容器。此外,它可以“重新启动”,因此它可能需要知道每个先前的运行周期有多长,然后将其添加到“时钟”的总持续时间中

Timer 只是一种在周期性基础上运行一些代码的简单方法。因为 Timer 只保证“至少”周期,所以应该避免将其用于简单的计数器加法,因为它会导致计算漂移(对于简单的时钟,这可能没什么大不了的,但是如果你需要任何精度,最好避免它)

简单时钟

import Foundation

public class SimpleClock {

internal var startedAt: Date? = nil
internal var totalRunningTime: TimeInterval = 0 // Used for pause/resume

var isRunning: Bool = false {
didSet {
if isRunning {
startedAt = Date()
} else {
totalRunningTime += currentCycleDuration
self.startedAt = nil
}
}
}

// This is the amount of time that this cycle has been running,
// that is, the amount of time since the clock was started to now.
// It does not include other cycles
internal var currentCycleDuration: TimeInterval {
guard let startedAt = startedAt else {
return 0
}
return Date().timeIntervalSince(startedAt)
}

func reset() {
isRunning = false
totalRunningTime = 0
}

// This is the "total" amount of time the clock has been allowed
// to run for, excluding periods when the clock was paused
var duration: TimeInterval {
return totalRunningTime + currentCycleDuration
}

}

好的,这是非常基本的概念。它只是一个容器,用于记录“循环”何时开始和停止以及管理“总体”持续时间(开始/暂停/恢复循环)

这一切都很好,但我们真正想要的是某种方法来确定周期是否“超时”。

闹钟

import Foundation

class AlarmClock: SimpleClock {

var timeout: TimeInterval = 0

var hasExpired: Bool {
return duration >= timeout
}

var timeRemaining: TimeInterval {
return max(timeout - duration, 0)
}

}

所有这一切都添加了一个“超时”周期的概念,并提供了一些额外的功能,允许用户轻松确定时钟是否已过期以及剩余时间量

例子

好的,这很好,但这是如何工作的(并帮助我们)

好吧,这是一个非常简单的例子。它有一个标签和两个按钮。一个按钮启动/暂停时钟,另一个按钮重置它。

标签显示闹钟的运行时间和剩余时间。如果他的时钟到期,它将自动重置。

该类包含一个 Timer,它会定期“滴答”并允许代码检查闹钟的当前状态。

Clocky

import UIKit

class ViewController: UIViewController {

@IBOutlet weak var durationLabel: UILabel!
@IBOutlet weak var cycleButton: UIButton!
@IBOutlet weak var resetButton: UIButton!

let alarmClock: AlarmClock = {
let clock = AlarmClock()
clock.timeout = 10.0
return clock
}()

var timer: Timer? = nil

var durationFormatter: DateComponentsFormatter {
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.minute, .second]
formatter.unitsStyle = .abbreviated
return formatter
}

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}

@IBAction func cycleClock(_ sender: Any) {
alarmClock.isRunning = !alarmClock.isRunning
if alarmClock.isRunning {
timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(tick), userInfo: nil, repeats: true)
} else {
timer?.invalidate()
timer = nil
}
updateDurationLabel()
updateCycleButtonState()
}

@IBAction func restartClock(_ sender: Any) {
timer?.invalidate()
timer = nil

alarmClock.reset()
updateDurationLabel()
updateCycleButtonState()
}

func updateCycleButtonState() {
if alarmClock.isRunning {
cycleButton.setTitle("Pause", for: [])
} else {
cycleButton.setTitle("Start", for: [])
}
}

func updateDurationLabel() {
durationLabel.text = "\(durationFormatter.string(from: alarmClock.duration)!)/\(durationFormatter.string(from: alarmClock.timeRemaining)!)"
}

@objc func tick() {
print("click")
updateDurationLabel()
if alarmClock.hasExpired {
restartClock(self)
}
}
}

现在,您还可以添加某种“内部”线程来定期检查时钟的状态并调用一个委托(delegate),然后可以用它来更新 UI,但这里的目的是分离关注点,并且这意味着您不会不必要地向系统添加另一个线程(并不是说您做不到,但这只是我不想添加的复杂性的一个层次;))

关于swift - 在 Swift 中以定义的时间停止计时器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51032287/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com