swift - 在显示暂停计时器 Int 的标签上显示暂停和恢复的计时器

标签 swift timer label resume pause

下面我的 swift 代码应该有 2 个按钮,一个开始按钮和一个暂停按钮。现在,我的代码在文本字段上获取一个 int 并对其进行计数并显示在标签 lblTime 上。当点击暂停按钮时,标签计时器停止。当再次点击它时,计时器会减少 1 秒,并且应该像点击开始按钮时一样倒计时。计时器从标签上的时间开始倒计时。我希望它倒数到零,而不是只倒数一秒。查看函数暂停。

import UIKit

   class ViewController: UIViewController, UITextFieldDelegate {
let MAX_LENGTH_PHONENUMBER = 2
let ACCEPTABLE_NUMBERS     = "0123456789"
var enterTime = UITextField()
var lblTime = UILabel()
var startBTN = UIButton()
var timer = Timer()
var counter = 0

var pauseBTN = UIButton()
var jake = 0


override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.

    [enterTime,lblTime,startBTN,pauseBTN].forEach{
        $0.backgroundColor = .systemRed
        view.addSubview($0)
        $0.translatesAutoresizingMaskIntoConstraints = false
    }

    enterTime.frame = CGRect(x: view.center.x-115, y: view.center.y-200, width: 60, height: 50)
    lblTime.frame = CGRect(x: view.center.x-115, y: view.center.y, width: 60, height: 50)
    pauseBTN.frame = CGRect(x: view.center.x-115, y: view.center.y+90, width: 60, height: 50)
    startBTN.frame = CGRect(x: view.center.x-115, y: view.center.y+200, width: 60, height: 50)

    startBTN.addTarget(self, action: #selector(startHit), for: .touchDown)

    pauseBTN.addTarget(self, action: #selector(pause), for: .touchDown)

    enterTime.placeholder = String("MM:SS")

    enterTime.delegate = self
    enterTime.addTarget(self, action: #selector(self.textFieldDidChange), for: UIControl.Event.editingChanged)

    pauseBTN.setTitle("pause", for: .normal)
    startBTN.setTitle("Start", for: .normal)
}

@objc func pause() {


    if jake == 0 {
        timer.invalidate()
        pauseBTN.setTitle("go", for: .normal)


    }
    else {
        timer.fire()
        pauseBTN.setTitle("pause", for: .normal)
        counter -= 1
        lblTime.text = formatSeconds(counter)
        if ( counter == 0 ) {
            timer.invalidate()}
    }

    jake += 1

}

@objc func startHit() {
    timer.invalidate()
    counter = convertToSeconds(from: enterTime.text!)
    lblTime.text = formatSeconds(counter)
    timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true)
}

@objc func timerAction() {
    counter -= 1
    lblTime.text = formatSeconds(counter)
    if ( counter == 0 ) {
        timer.invalidate()
    }
}
func convertToSeconds(from timeString: String) -> Int {
    let components = timeString.components(separatedBy: ":")
    if components.count == 2 {
        let minutes = Int(components[0]) ?? 0
        let seconds = Int(components[1]) ?? 0
        return (minutes * 60) + seconds
    } else if components.count == 3 {
        let hours = Int(components[0]) ?? 0
        let minutes = Int(components[1]) ?? 0
        let seconds = Int(components[2]) ?? 0
        return (hours * 60 * 60) + (minutes * 60) + seconds
    } else {
        return 0
    }
}
func formatSeconds(_ totalSeconds: Int) -> String {
    let formatter = DateComponentsFormatter()
    formatter.unitsStyle = .positional
    formatter.allowedUnits = [.minute, .second]
    formatter.zeroFormattingBehavior = .pad
    return formatter.string(from: TimeInterval(totalSeconds))!
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    let newLength: Int = textField.text!.count + string.count - range.length
    let numberOnly = NSCharacterSet.init(charactersIn: ACCEPTABLE_NUMBERS).inverted
    let strValid = string.rangeOfCharacter(from: numberOnly) == nil
    return (strValid && (newLength <= MAX_LENGTH_PHONENUMBER))
}



@objc func textFieldDidChange(_ textField: UITextField) {
    if  textField.text!.count == 2  {
        textField.text = textField.text! + ":00"
    }
}
 }

最佳答案

要暂停/停止计时器,请使用 timer.invalidate()timer = nil 两者,因为在计时器启动时,它总是创建新实例。

class ViewController: UIViewController, UITextFieldDelegate {
    let MAX_LENGTH_PHONENUMBER = 2
    let ACCEPTABLE_NUMBERS     = "0123456789"
    var enterTime = UITextField()
    var lblTime = UILabel()
    var startBTN = UIButton()
    var timer:Timer? = Timer()
    var counter = 0

    var pauseBTN = UIButton()
    var isPaused = false

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        [enterTime,lblTime,startBTN,pauseBTN].forEach{
            $0.backgroundColor = .systemRed
            view.addSubview($0)
            $0.translatesAutoresizingMaskIntoConstraints = false
        }
        enterTime.frame = CGRect(x: view.center.x-115, y: view.center.y-200, width: 60, height: 50)
        lblTime.frame = CGRect(x: view.center.x-115, y: view.center.y, width: 60, height: 50)
        pauseBTN.frame = CGRect(x: view.center.x-115, y: view.center.y+90, width: 60, height: 50)
        startBTN.frame = CGRect(x: view.center.x-115, y: view.center.y+200, width: 60, height: 50)

        startBTN.addTarget(self, action: #selector(startHit), for: .touchDown)

        pauseBTN.addTarget(self, action: #selector(pause), for: .touchDown)

        enterTime.placeholder = String("MM:SS")

        enterTime.delegate = self
        enterTime.addTarget(self, action: #selector(self.textFieldDidChange), for: UIControl.Event.editingChanged)

        pauseBTN.setTitle("pause", for: .normal)
        startBTN.setTitle("Start", for: .normal)
    }

    @objc func pause() {

        if !isPaused {
            timer?.invalidate()
            timer = nil
            pauseBTN.setTitle("go", for: .normal)
        }
        else {
            timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true)
            pauseBTN.setTitle("pause", for: .normal)
        }
        isPaused = !isPaused
    }

    @objc func startHit() {
        isPaused = false
        timer?.invalidate()
        counter = convertToSeconds(from: enterTime.text ?? "")
        lblTime.text = formatSeconds(counter)
        timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true)
    }

    @objc func timerAction() {
        if ( counter == 0 ) {
            timer?.invalidate()
            timer = nil
            return
        }
        counter -= 1
        lblTime.text = formatSeconds(counter)
    }
    func convertToSeconds(from timeString: String) -> Int {
        let components = timeString.components(separatedBy: ":")
        if components.count == 1 {
            let minutes = Int(components[0]) ?? 0
            return minutes * 60
        } else if components.count == 2 {
            let minutes = Int(components[0]) ?? 0
            let seconds = Int(components[1]) ?? 0
            return (minutes * 60) + seconds
        } else if components.count == 3 {
            let hours = Int(components[0]) ?? 0
            let minutes = Int(components[1]) ?? 0
            let seconds = Int(components[2]) ?? 0
            return (hours * 60 * 60) + (minutes * 60) + seconds
        } else {
            return 0
        }
    }
    func formatSeconds(_ totalSeconds: Int) -> String {
        let formatter = DateComponentsFormatter()
        formatter.unitsStyle = .positional
        formatter.allowedUnits = [.minute, .second]
        formatter.zeroFormattingBehavior = .pad
        return formatter.string(from: TimeInterval(totalSeconds)) ?? ""
    }
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

        let newLength: Int = (textField.text?.count ?? 0) + string.count - range.length
        let numberOnly = NSCharacterSet.init(charactersIn: ACCEPTABLE_NUMBERS).inverted
        let strValid = string.rangeOfCharacter(from: numberOnly) == nil
        return (strValid && (newLength <= MAX_LENGTH_PHONENUMBER))
    }



    @objc func textFieldDidChange(_ textField: UITextField) {
        if let text = textField.text, text.count == 2 {
            textField.text = text + ":00"
        }
    }
}

关于swift - 在显示暂停计时器 Int 的标签上显示暂停和恢复的计时器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59475287/

相关文章:

ios - 如何在 Swift 中从 AVAudioPlayer 获取锁定屏幕/控制中心上的音频控件

c# - Windows服务中的多线程

ios - 如何在几秒钟后停止计时器

javascript - 1 分钟倒计时 Javascript

JavaFX标签不会持续更新

ios - 无法识别的选择器 - 异常

ios - 您能否只允许具有特定电子邮件地址的用户注册和使用您的应用程序

Swift UITableView 不会调整到更大的尺寸

javascript - 在 Highstocks 中,将鼠标悬停在图表上时如何更改默认时间/日期标签?

Python Tkinter 更新标签文本会将旧文本保留在那里,直到函数退出