Adding another countdown timer to a viewcontroller that already has a working one

Hi All,

I’ve made an very basic app for personal use to use as a shot clock for pool tournaments which works fine for adding names, scores and the single shot clock as well as adding a 15 second extension to a players shot clock but I need to have another countdown timer to run from 45 minutes down to 0 and needs to be independent from the shot clock timer. Each time I’ve tried to create another timer to use as the match clock and run it then it affects the shot clock timer countdown.

Here is the code I currently have working.

If somebody could help with just adding in another timer that doesn’t get affected by the other timer then I would be very grateful.

Here is the project file as it is so far.

Thank you.

Hi @mwr_allen

Welcome to the community

Just create an additional timer. It’s that easy.

You’ve already got two timers timer and matchTimer so just create another one and give it whatever name you require and then set up the parameters for how you want it to operate.

All the timers should be completely independent of each other. They cannot refer to the same counter function as you have currently set it up to do. That’s why one is interfering with the other.

Create a separate @objc func which responds to the specific timer that is being triggered.

Also give your code some room to breathe. It is very cramped and difficult to read.

This:

    @IBAction func ext1resetaudio(_ sender: Any)
    {audioPlayer.stop()
        audioPlayer.currentTime = 0
        isPlaying = false}

should be changed to this:

    @IBAction func ext1resetaudio(_ sender: Any) {
        audioPlayer.stop()
        audioPlayer.currentTime = 0
        isPlaying = false
    }

Do you see how much easier it is to read?

Also name your variables using camel case. For example instead of

matchtimer

name it

matchTimer

Thanks for the reply,
I’ve tried adding another timer for Match Clock and I’ve linked the label as “matchLabel” and also a button with links “matchStart” and “matchReset” names and when trying to add @objc with the same code as my existing shot timer and changing “label.text” to “matchTimer.text” I get this error.
@objc can only be used with members of classes, @objc protocols, and concrete extensions of classes
Also, when trying to add a separate @objc func counter() it says invalid redeclaration of counter()

Create a separate counter function for each timer and tailor the code to suit. Then point the #selector to it’s own function as in this example from your ViewController file:

    @IBAction func start(_ sender: Any) {
        timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(counter), userInfo: nil, repeats: true)
        sliderOutlet.isHidden = true
        startOutlet.isHidden = true
    }

    @IBOutlet weak var matchstartOutlet: UIButton!

    @IBAction func matchStart(_ sender: Any) {
        matchTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(matchTimerCounter), userInfo: nil, repeats: true)
    }

    @objc func counter() {
        seconds -= 1
        label.text = String(seconds) + ""
        matchClockTimer.text = String(seconds) + ""
        if (seconds == 0) {
            timer.invalidate()
        }
        
        if (seconds == 6) {
            sliderOutlet.isHidden = false
            startOutlet.isHidden = false
            audioPlayer.play()
        }
    }

    @objc func matchTimerCounter() {
        //  Your code for this counter goes here
    }

Hi there,

Thanks to your help with this I now have two separately running timers!

I just now have one more question. With regard to the match clock timer counting down, how can I get this to read and count down in minutes/seconds as I can only seem to have it running in seconds and was even just going to leave it as 2700 seconds but would really like it to read as 45:00 > 44:59>44:58 etc.

I’ve attached my current project file as it is, please forgive the untidiness which I will get to once its working as desired.

Thank you.

Marcus.

Hi Marcus. I’m away for 4 days and will soon be out of mobile range.

I’ll get back to you mid next week.

:grinning:

Have a great time! :grin::+1:

Hi Marcus,

I’ve downloaded your code from the above link and gone through it to get the App to display the match countdown timer in minutes and seconds.

Essentially I created a function that takes the matchCounter and then using some math creates a minutes component and a seconds component and then returns that in a String to place in the matchLabel

The function is as follows:

    //  Converts the countdown seconds to a String
    func convertCountDownToMinutesAndSeconds(timerSeconds: Int) -> String {
        var minutesString = ""
        var secondsString = ""
        let minutes = Int(timerSeconds / 60)
        let seconds = timerSeconds % 60

        minutesString = minutes < 10 ? "0\(minutes)" : "\(minutes)"
        secondsString = seconds < 10 ? "0\(seconds)" : "\(seconds)"

        return minutesString + ":" + secondsString
    }

So wherever you need to update the matchLabel the code is:

matchLabel.text = convertCountDownToMinutesAndSeconds(timerSeconds: matchCounter)

Hope that helps.

Hi there, Many thanks for your help, I haven’t been back on here for a little while so only just seen this reply from you.
I actually did it a slightly different way and now works fine anyway and also added a sound file for match clock from 10 seconds down to 0 and the way I made the match clock work was that I wasn’t actually using “hours” in the app anywhere so called hours as seconds as a bit of a makeshift way to get it to work so now I think it’s working as I need it to. for now anyway until I think of something else to add to it. :slight_smile:
I’ve attached it as it is here.

Thanks again.
Marcus.

Hi All,
I’m trying to build a simple stopwatch app that I will use to time pool players when they play a 6 ball shootout (players break off and clear 6 balls in the quickest time).
The stopwatch part itself I have working fine with buttons for start, stop, reset and penalty (adds 5 seconds penalty to the time) and I have added the code to run a sound using AVAudioPlayer but the part I’m really stuck with is what code to put in to automatically play the sound when the timer reaches the same time of the first players time.
For example: player 1 breaks and clears all 6 balls in a time of 00:45:22 and when player 2 plays and their time reaches 00:45:22 the sound will play by itself without the need for manual button.
Currently I only know how to get Xcode to play a sound at a set time.
I would really appreciate any help with this as I’m very much a beginner with Xcode and a bit stumped after not finding anything specific to what I need online.
I’ve attached an image of my app so far. The top one is the running stopwatch and the player name to the left and under that I have the other player and also tried putting in a Text Field which I was trying to enter the first players time manually then reset the stopwatch and have the sound play when it reached the time I entered into the Text Field which hasn’t quite worked.
Here’s my code too.
Thanks.


//
// ViewController.swift
// 6 Ball Shootout Timer
//
// Created by Marcus Allen on 17/01/2023.
//

import UIKit
import AVFoundation
import SwiftUI
import ClockKit

class ViewController: UIViewController, UITextFieldDelegate{
var timer = Timer()
var (hours, minutes, seconds, fractions) = (0, 0, 0, 0)
var audioPlayer = AVAudioPlayer()

@IBOutlet weak var bg: UIImageView!
@IBOutlet weak var timerLabel: UILabel!
@IBOutlet weak var fractionsLabel: UILabel!
@IBOutlet weak var startOutlet: UIButton!
@IBOutlet weak var stopOutlet: UIButton!
@IBOutlet weak var resetOutlet: UIButton!
@IBOutlet weak var penaltyOutlet: UIButton!
@IBOutlet weak var timeToBeat: UITextField!

@IBAction func start(_ sender: UIButton) {
    timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(ViewController.keepTimer), userInfo: nil, repeats: true)
    startOutlet.isHidden = true
}

@IBAction func stop(_ sender: UIButton) {
    timer.invalidate()
    startOutlet.isHidden = false
}

@IBAction func reset(_ sender: UIButton) {
    (hours, minutes, seconds, fractions) = (0, 0, 0, 0)
    timerLabel.text = "00:00"
    fractionsLabel.text = ":00"
}
@IBAction func penalty(_ sender: UIButton) {
    seconds += 5
}

@IBAction func playerName(_ sender: UITextField) {
    sender.resignFirstResponder()
}
override func viewDidLoad(){
    super.viewDidLoad()
    
    bg.loadGif(name: "vid2")
    
    do
    {let audioPath = Bundle.main.path(forResource: "endgame", ofType: ".mp3")
        try audioPlayer = AVAudioPlayer(contentsOf: URL(fileURLWithPath: audioPath!))
    }
    catch {
        //ERROR
        
    }    }

@objc func keepTimer() {
    fractions += 1
    if fractions > 99 {
        seconds += 1
        fractions = 0
    }
    
    
    if seconds == 60 {
        minutes += 1
        seconds = 0
    }