Swift |计时器不会在无效呼叫时停止,而是加速?

Swift | The timer wont stop on invalidate call, rather speeds up?

我在这个应用程序中使用计时器制作了一个秒表,并添加了开始停止按钮来暂停和播放。 当按下按钮时,它被发送到一个使计时器无效的函数,它应该停止。 但奇怪的是,当按下停止按钮时,计时器并没有停止而是以某种方式加速了 我没有更改时间间隔,只是声明了一次。

我曾尝试在按下开始按钮后将其禁用,甚至将其隐藏。还尝试更改时间间隔但没有任何效果。我越按开始停止按钮,它越加速,开始比提到的时间间隔快得多。

startButton.frame = CGRect(x: 0, y: UIScreen.main.bounds.height * 0.9 , width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height * 0.1)
    startButton.setTitle("Start Timer", for: .normal)
    self.view.addSubview(startButton)
    startButton.setTitleColor(.white , for: .normal)
    startButton.backgroundColor = .red
    startButton.addTarget(self, action: #selector(playButton(_:)), for: .allTouchEvents)

    stopButton.frame = CGRect(x: 0, y: UIScreen.main.bounds.height * 0.9 , width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height * 0.1)
    stopButton.setTitle("Stop Timer", for: .normal)
    stopButton.setTitleColor(.white , for: .normal)
    stopButton.backgroundColor = .red
    stopButton.addTarget(self, action: #selector(pauseButton(_:)), for: .allTouchEvents)
@objc func playButton(_ sender : Any)
{
    timer = Timer.scheduledTimer(timeInterval: 1, target: self , selector: #selector(updateTimer), userInfo: nil, repeats: true)
    startButton.isEnabled = false
    stopButton.isEnabled = true
    isRunning = true
    self.view.addSubview(stopButton)
    startButton.isHidden = true
    stopButton.isHidden = false



}

@objc func pauseButton(_ sender: Any) {
    self.view.addSubview(startButton)
    timer.invalidate()

    stopButton.isHidden = true
    startButton.isHidden = false

    startButton.isEnabled = true
    stopButton.isEnabled = false

    isRunning = false

}


@objc func updateTimer(_ sender : Any)
{
    counter += 0.1
    titleLabel.text = String(format: "%.1f", counter)
}

尝试通过隐藏停止按钮同时添加两个按钮,并在单击按钮时隐藏和取消隐藏按钮。当您尝试停止计时器时,您的播放按钮方法每次都是 运行

据我所知,你有两个错误。

另一个答案提到了第一个。这是一个真实的建议,你不应该总是添加一个新的 UIButton 并且应该只为每个按钮使用 hide/unhide 属性。

第二个错误在于添加目标的方式。您正在使用 .allTouchEvents,但是您可能打算使用 .touchUpInside 作为您的控制状态。

请参阅以下更正后的代码供您参考:

import UIKit

class ViewController: UIViewController {

@IBOutlet weak var titleLabel: UILabel!

var startButton: UIButton!
var stopButton: UIButton!
var timer: Timer!
var counter: Double = 0.0

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

    startButton = UIButton(frame: CGRect(x: 0, y: UIScreen.main.bounds.height * 0.9 , width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height * 0.1))
    startButton.setTitle("Start Timer", for: .normal)
    startButton.setTitleColor(.white , for: .normal)
    startButton.backgroundColor = .red
    startButton.addTarget(self, action: #selector(playButton(_:)), for: .touchUpInside)
    self.view.addSubview(startButton)
    self.startButton.isHidden = false

    stopButton = UIButton(frame: CGRect(x: 0, y: UIScreen.main.bounds.height * 0.9 , width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height * 0.1))
    stopButton.setTitle("Stop Timer", for: .normal)
    stopButton.setTitleColor(.white , for: .normal)
    stopButton.backgroundColor = .red
    stopButton.addTarget(self, action: #selector(pauseButton(_:)), for: .touchUpInside)
    self.view.addSubview(stopButton)
    self.stopButton.isHidden = true
}

@objc func playButton(_ sender : Any) {
    timer = Timer.scheduledTimer(timeInterval: 1, target: self , selector: #selector(updateTimer), userInfo: nil, repeats: true)

    startButton.isEnabled = false
    stopButton.isEnabled = true
    startButton.isHidden = true
    stopButton.isHidden = false
}

@objc func pauseButton(_ sender: Any) {
    timer.invalidate()

    stopButton.isHidden = true
    startButton.isHidden = false
    startButton.isEnabled = true
    stopButton.isEnabled = false
}


@objc func updateTimer(_ sender : Any)
{
    counter += 0.1
    titleLabel.text = String(format: "%.1f", counter)
}
}

您已经有 2 个正确答案,但我会提出我的 2p,因为我认为您开始的前提不正确。

你最大的错误是一开始就有 2 个按钮。如果您只有一个按钮并根据需要设置样式,您就不会遇到这个问题。

class MyTest {
    let magicButton = UIButton()
    let timer: Timer?

    override viewDidLoad() {
        super.viewDidLoad()

        // Setup Button
        magicButton.addTarget(self, action: #selector(buttonPress(_:)), for: .allTouchEvents)
        magicButton.setTitleColor(.white , for: .normal)
        magicButton.frame = yourFrame
        view.addSubview(magicButton)

        customiseButton()
    }

    @objc private func buttonPress() {
        if timer == nil {
            timer = Timer.scheduledTimer(timeInterval: 1, target: self , selector: #selector(updateTimer), userInfo: nil, repeats: true)
        } else {
            timer.invalidate()
        }

        customiseButton()
    }

    private func customiseButton() {
        let isStartButton = timer == nil
        let buttonTitle = isStartButton ? "Start" : "Stop"
        let buttonBackgroundColor: UIColor = isStartButton ? .green : .red

        magicButton.setTitle(buttonTitle, for: .normal)
        magicButton.backgroundColor = buttonBackgroundColor
    }
}

// add updateTimer function too

这样一来,您需要维护的代码就会更少,而且隐藏/显示的内容之间不会发生冲突,因此可能出错的事情也会更少。 魔法 发生在 buttonPress 方法中,如果计时器启动,您将停止它,否则您启动一个,然后快速更新按钮 UI.