Run Counter while button press - swift

I am very new to swift and I want to make a button work like this:
Press the Button and hold. While the Button is pressed the label value goes up like every second +1 until the button is released.
This is what I get so far:
class ViewController: UIViewController {
var counter = 0;
override func viewDidLoad() {
super.viewDidLoad();
}
#IBOutlet weak var label: UILabel!
#IBAction func btn(_ sender: Any) {
if (sender as AnyObject).state != .ended{
counter+=1;
// wait 100ms
self.label.text = String (counter);
}
}
}
This is how I linked it:

You can achieve this using the UIButton actions Touch Down and Touch Up Inside
class ViewController: UIViewController {
var timer : Timer?
var startTime = 0
var timerReset = true // I don't know what logic you want. This basically has been added so the number is not set to 0 immediately when you release the button. You can also add another button to reset startTime variable and the label
#IBOutlet weak var numberLabel: UILabel!
#IBOutlet weak var numberButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
numberLabel.text = String(startTime) //initial value
// Do any additional setup after loading the view.
}
#IBAction func holdingTheButton(_ sender: Any) {
print("I am holding")
timerReset = false // reset to false since you are holding the button
guard timer == nil else { return }
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)
}
#IBAction func buttonReleased(_ sender: Any) {
print("button released")
startTime = 0
timer?.invalidate()
timer = nil
timerReset = true // reset to true since you released.
}
#objc func updateTime(){
//update label every second
print("updating label ")
if timerReset {
startTime = 0
}
startTime += 1
numberLabel.text = String(startTime)
}
}
IMPORTANT: Make sure you are connecting in the right way. Touch Down has to be used if you want to call the function while you hold the button:
In your console, you should see this happening if you release the button after 10 SECONDS:
If you want to have a button to reset, you can just add the it and then connect it to the following function (but also make sure you remove the bool timeReset and the if statement inside updateTime:
#IBAction func resetTimer(_ sender: Any) {
startTime = 0
numberLabel.text = String(startTime)
}

You can achieve it using two sent event touch of UIButton and a Timer.
var counter = 0
var timer: Timer?
#IBAction func buttonTouchUpInside(_ sender: Any) {
timer?.invalidate()
print(counter)
}
#IBAction func buttonTouchDown(_ sender: Any) {
timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(increaseCount), userInfo: nil, repeats: true)
}
#objc func increaseCount() {
counter += 1
print(counter)
}

Related

Implement a dictionary value into a count down timer

I’m making an appllication quiz in which i want to implement the value of the dictionary to be the intial value of the countdown timer so if the "soft" key is targeted the count down timer starts from 300 instead of 60
import UIKit
class ViewController: UIViewController {
let eggTimes :[String:Int]=["Soft":300,"Medium":420,"Hard":720
]
var count: Int = 60
func startCountDown() {
Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateCounter), userInfo: nil, repeats: true)
}
#objc func updateCounter() {
if count>0 {
count-=1
countDownLabel.text = "\(count)"
print(count)
}
}
#IBOutlet weak var countDownLabel: UILabel!
#IBAction func hardnessSelected(_ sender: UIButton) {
startCountDown()
let hardness=sender.currentTitle!
let result = eggTimes[hardness]!
print(result)
}
} ```
let hardness=sender.currentTitle!
count = eggTimes[hardness]!
startCountDown()
Set count before starting the countdown
#IBAction func hardnessSelected(_ sender: UIButton) {
let hardness = sender.currentTitle!
count = eggTimes[hardness]!
startCountDown()
}
But it's easier to assign tags to the 3 buttons, the three values 300, 420 and 720.
Then you can delete the dictionary and write
#IBAction func hardnessSelected(_ sender: UIButton) {
count = sender.tag
startCountDown()
}

How can I make variables inside an IBAction public to all view controllers?

So I'm trying to make a Chess Time app, where both players have access to a clock and they change the time between bullet(3minutes), Blitz(5minutes), and Rapid(10Minutes). Well in my second view controller SettingsController I made 3 IBActions UIButtons for this.
#IBAction func bulletPressed(_ sender: UIButton) {
var storedTime = bullet
self.delegate?.storedTimeTimer()
self.navigationController?.popViewController(animated: true)
}
#IBAction func blitzPressed(_ sender: UIButton) {
var storedTime = blitz
}
#IBAction func rapidPressed(_ sender: UIButton) {
var storedTime = rapid
}
This is my SettingsController, my whole point is trying to get the storedTime into the first controller. I tried to use a delegate, but I couldn't get it to work.
Here is the full First Controller:
import UIKit
class ChessTimer: UIViewController {
#IBOutlet weak var playerTimer1: UILabel!
#IBOutlet weak var playerTimer2: UILabel!
var timer = Timer()
var time = 10
var isTimerRunning = false
override func viewDidLoad() {
super.viewDidLoad()
if isTimerRunning == false {
runTimer()
}
}
#IBAction func restartButton(_ sender: UIButton) {
}
#IBAction func pausePressed(_ sender: UIButton) {
timer.invalidate()
}
#IBAction func settingsPressed(_ sender: UIButton) {
performSegue(withIdentifier: "goToSettings", sender: self)
}
func runTimer() {
timer = Timer.scheduledTimer(timeInterval: 1, target: self,selector:
(#selector(ChessTimer.updateTimer)),userInfo: nil, repeats: true)
isTimerRunning = true
}
#objc func updateTimer() {
if storedTime! < 1 {
timer.invalidate()
playerTimer1.text = "00:00"
playerTimer2.text = "00:00"
}
else {
storedTime! -= 1
playerTimer1.text = prodTimeString(time: TimeInterval(storedTime)!)
}
}
func prodTimeString(time: TimeInterval) -> String {
let prodMinutes = Int(time) / 60 % 60
let prodSeconds = Int(time) % 60
return String(format: "%02d:%02d", prodMinutes, prodSeconds)
}
#IBAction func playerButton1(_ sender: UIButton) {
}
#IBAction func playerButton2(_ sender: UIButton) {
}
}
extension ChessTimer: SettingsControllerDelegate {
func storedTimeTimer() {
}
}
This is the second full controller
import UIKit
class SettingsController: UIViewController {
var bullet = "03:00"
var blitz = "05:00"
var rapid = "10:00"
var storedTime = 0
var delegate: SettingsControllerDelegate?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func bulletPressed(_ sender: UIButton) {
var storedTime = bullet
self.delegate?.storedTimeTimer()
self.navigationController?.popViewController(animated: true)
}
#IBAction func blitzPressed(_ sender: UIButton) {
var storedTime = blitz
}
#IBAction func rapidPressed(_ sender: UIButton) {
var storedTime = rapid
}
}
protocol SettingsControllerDelegate {
func storedTimeTimer()
}
This can be achieved using a Constants.swift file.
Click File -> New -> File -> Swift File and then name it Constants.swift.
In Constants.swift, declare var storedTime = 0.
Delete var storedTime = 0 from your view controllers, you'll only need it in Constants.swift. (So delete it from SettingsController, etc.)
The storedTime variable will now be public to all view controllers. 👍
Hope this helps someone!

Timer counts but doesn´t desplay

I just started to learn how to code and speak English^^
When I go from secondViewController to ViewController, a timer starts. A label shows the timer.
My problem is, when I go from secondViewController to ViewController for the second time, the label doesn´t show the timer. But the timer continue to count (I printed it out). Why the label doesn´t shoews the timer ?
I would be very grateful for your help
ViewController
var habit = 0
var statusFirst = false
class ViewController: UIViewController {
var firstTitel = ""
var secondTitels = ""
var timerTime = 0
var timer = Timer()
#IBOutlet weak var titelLabel: UILabel!
#IBOutlet weak var dateLabel: UILabel!
#IBOutlet weak var secondTitel: UILabel!
#IBOutlet weak var secondDate: UILabel!
#objc func processTimer() {
timerTime += 1
dateLabel.text = String(timerTime)
print(timerTime)
}
override func viewDidLoad() {
super.viewDidLoad()
// Hide Label - START
print(habit)
if habit == 0 {
titelLabel.isHidden = true
secondTitel.isHidden = true
dateLabel.isHidden = true
secondDate.isHidden = true
timer.invalidate()
}else if habit == 1 {
titelLabel.isHidden = false
secondTitel.isHidden = true
dateLabel.isHidden = false
secondDate.isHidden = true
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.processTimer), userInfo: nil, repeats: true)
}else if habit == 2 {
titelLabel.isHidden = false
secondTitel.isHidden = false
dateLabel.isHidden = false
secondDate.isHidden = false
}
// Hide Label - END
let titelObject = UserDefaults.standard.object(forKey: "firstTitel")
if let titel = titelObject as? String {
titelLabel.text = titel
}
let titellObject = UserDefaults.standard.object(forKey: "secondTitel")
if let titell = titellObject as? String {
secondTitel.text = titell
}
// 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.
}
}
SecondViewController
class SecondViewController: UIViewController {
var titelSecondViewController = ""
var dateSecondViewController = 0
#IBOutlet weak var titelField: UITextField!
#IBOutlet weak var dateField: UITextField!
#IBOutlet weak var okButton: UIButton!
#IBAction func okButtonAction(_ sender: Any) {
titelSecondViewController = titelField.text!
if let datefield = dateField.text {
if datefield == "" {
dateSecondViewController = 0
}else{
dateSecondViewController = Int(datefield)!
}
}else{
print("lol")
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
// Segue - Start
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "toViewController" {
let viewController = segue.destination as! ViewController
habit += 1
print(habit)
if habit == 1 {
statusFirst = true
UserDefaults.standard.set(titelSecondViewController, forKey: "firstTitel")
}else if habit == 2{
UserDefaults.standard.set(titelSecondViewController, forKey: "secondTitel")
}else{
return
}
}
}
// Segue - End
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
In first case habit = 1 so the timer is called
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.processTimer), userInfo: nil, repeats: true)
since the timer has a strong reference and you don't invalidate() it inside viewDidDisappear , it keeps the VC in memory after you dismiss it
//
In second time habit = 2 and you don't init the time inside it's if statement then the label of the second instance ( the presented one ) doesn't update , while the hidden dismissed one do

Counter wont subtract on button press?

I am trying to get my setCount to -1 each time the endSetPressed action is called.
I have included setCount -= 1 to the updateTimer function so that when endSetPressed is pressed, it should -1 from the setCount and then start the restCount timer. However in practice it doesnt seem to show it doing the -1 in the app it just stays fixed at the starting setCount value.
Another issue was that I want to be able to see the value of restRemainingCountdownLabel as the user is setting the restStepperValueChanged value, i figured this was done via 'restRemainingCountdownLabel.text = String(restCount)' however as im using 'restCount = Int(sender.value)*60' to generate a value in minutes, its showing the restRemainingCountdownLabel in seconds rather than mins, Appreciate some guidance on that one too!
Here is my code:
#IBOutlet weak var restRemainingCountdownLabel: UILabel!
#IBOutlet weak var setsRemainingCountdownLabel: UILabel!
#IBOutlet weak var numberOfSetsLabel: UILabel!
#IBOutlet weak var numberOfRestLabel: UILabel!
#IBOutlet weak var adjustSetsStepper: UIStepper!
#IBOutlet weak var adjustRestStepper: UIStepper!
var restTimer: Timer?
var restCount = 0
var setCount = 0
#IBAction func endSetPressed(_ sender: Any) {
restTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(RestController.updateTimer), userInfo: nil, repeats: true)
}
#IBAction func setStepperValueChanged(_ sender: UIStepper) {
numberOfSetsLabel.text = Int(sender.value).description
setCount = Int(sender.value)
setsRemainingCountdownLabel.text = String(setCount)
}
#IBAction func restStepperValueChanged(_ sender: UIStepper) {
numberOfRestLabel.text = Int(sender.value).description
restCount = Int(sender.value)*60
restRemainingCountdownLabel.text = String(restCount)
}
#IBAction func resetSetsButton(_ sender: Any) {
//setCount = Int
}
override func viewDidLoad() {
super.viewDidLoad()
}
func updateTimer() {
if (setCount > 0){
setCount -= 1
}
if (restCount > 0){
let minutes = String(restCount / 60)
let seconds = String(restCount % 60)
restRemainingCountdownLabel.text = minutes + ":" + seconds
restCount -= 1
}
}
Have a look at your updateTimer() method, first line:
if (setCount > 0)
if setCount > 0 then subtract 1 from setCount
but...here you've declared setCount with a value of 0
var setCount = 0
So, you never end up in your if part :)
How to Debug This
The next time you have a problem like this, try adding some print() statements to your code.
In your case you could do something like this:
#IBAction func endSetPressed(_ sender: Any) {
print("endSetPressed")
restTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(RestController.updateTimer), userInfo: nil, repeats: true)
}
#IBAction func setStepperValueChanged(_ sender: UIStepper) {
numberOfSetsLabel.text = Int(sender.value).description
setCount = Int(sender.value)
setsRemainingCountdownLabel.text = String(setCount)
}
#IBAction func restStepperValueChanged(_ sender: UIStepper) {
numberOfRestLabel.text = Int(sender.value).description
restCount = Int(sender.value)*60
restRemainingCountdownLabel.text = String(restCount)
}
#IBAction func resetSetsButton(_ sender: Any) {
//setCount = Int
}
override func viewDidLoad() {
super.viewDidLoad()
}
func updateTimer() {
print("updateTimer")
if (setCount > 0){
print("setCount > 0")
setCount -= 1
print("setCount is now \(setCount)")
}
if (restCount > 0){
print("restCount > 0")
let minutes = String(restCount / 60)
let seconds = String(restCount % 60)
restRemainingCountdownLabel.text = minutes + ":" + seconds
restCount -= 1
print("restCount is now \(restCount) - minutes: \(minutes) - seconds: \(seconds)")
}
}
That should give you some indications about what is going on and the "path" your code follows.
Hope that helps you.

Stopwatch code Issue

I am trying to create a stopwatch app, for some reason when I press the start button in the app, instead of it going, 1,2,3,4,5 etc. It shows this '<'. I have gone over the code but I can find nothing.
class ViewController: UIViewController {
var timer = NSTimer()
var time = 0
func result() {
time + 1
timeLabel.text = "\(timer)"
}
#IBOutlet var timeLabel: UILabel!
#IBAction func stop(sender: AnyObject) {
timer.invalidate()
time = 0
timeLabel.text = "0"
}
#IBAction func timeButton(sender: AnyObject) {
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("result"), userInfo: nil, repeats: true)
}
}
You have a typo: timeLabel.text = "\(timer)" should be timeLabel.text = "\(time)".
Also, time + 1 should be time += 1. With those changes, the following code works:
class ViewController: UIViewController {
var timer = NSTimer()
var time = 0
func result() {
time += 1
timeLabel.text = "\(time)"
}
#IBOutlet var timeLabel: UILabel!
#IBAction func stop(sender: AnyObject) {
timer.invalidate()
time = 0
timeLabel.text = "0"
}
#IBAction func timeButton(sender: AnyObject) {
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: #selector(result), userInfo: nil, repeats: true)
}
}