简体   繁体   English

斯威夫特| 计时器不会在无效呼叫上停止,而是加快速度吗?

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

i have made a stop watch using Timer in this app and added start stop button to pause and play the same. 我已经在此应用中使用Timer进行了秒表,并添加了“开始停止”按钮以暂停并播放相同内容。 When the press button is pressed, it is sent to a function which invalidates the timer and it should stop. 当按下按钮时,它将发送到使计时器无效的功能,并且应该停止。 But Strangely Enough When The Stop Button Is Pressed, Instead Of Stopping The Timer Somehow Speeds Up i have not changed the time interval other than once just declaring it. 但是当按下“停止”按钮时,奇怪的是,而不是以某种方式停止计时器,我没有改变时间间隔,只是一次声明它。

i have tried to disabled the start button once it is pressed and even hide it. 我曾尝试禁用启动按钮,一旦按下它甚至将其隐藏。 also tried changing the time interval but nothing works. 也尝试更改时间间隔,但没有任何效果。 the more i press the start stop button , the more it speeds up and starts going much faster than the mentioned time interval. 我按启动停止按钮的次数越多,它的速度就越快,并且开始运行的速度比上述时间间隔快得多。

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)
}

Try to add both the buttons at the same time by hidding the stop button and just hide and unhide the buttons on button click. 尝试通过隐藏停止按钮来同时添加两个按钮,并在单击按钮时隐藏和取消隐藏按钮。 Your play button method is running every time, when you are trying to stop the timer 当您尝试停止计时器时,您的播放按钮方法每次都会运行

As far as I can recognize, you have 2 mistakes. 据我所知,您有两个错误。

First one is mentioned by the other answer. 另一个答案提到第一个。 It is a true suggestion that you shouldn't always add a new UIButton and should use just hide/unhide property for each button. 确实建议您不要总是添加新的UIButton,而应仅对每个按钮使用hide / unhide属性。

Second mistake is on how you add a target. 第二个错误是您如何添加目标。 You are using .allTouchEvents, however you might intent to use .touchUpInside as your control state. 您正在使用.allTouchEvents,但是您可能打算将.touchUpInside用作控件状态。

Kindly see the below corrected code for your reference: 请参阅以下更正的代码以供参考:

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)
}
}

You have 2 correct answers already, but I'll throw in my 2p as I think the premises you've started on hasn't been correct. 您已经有2个正确答案,但是我会投入2p,因为我认为您开始的前提不正确。

Your biggest mistake is having 2 buttons in the first place. 您最大的错误是首先拥有2个按钮。 You would not have had the issue if you only had one buttons and styled it as needed. 如果您只有一个按钮并根据需要设置样式,则不会有问题。

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

This way you have less code to maintain and no conflict between stuff being hidden / shown, so fewer things that could go wrong. 这样,您需要维护的代码更少,并且隐藏/显示的内容之间没有冲突,因此可以减少出错的地方。 The magic is happening in the buttonPress method where if a timer is started you stop it, otherwise you start one, followed by a quick update to the button UI. 神奇的事情发生在buttonPress方法中,如果启动了计时器,则将其停止,否则将启动该计时器,然后快速更新按钮UI。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM