How do I set a label to a value from a separate table view controller? - swift

So I'm setting up a timer in swift that takes text entered from another view controller. I'm not sure how to set the timer label as the value "timerTime" which has a member called "time" from another controller.
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var timerLabel: UILabel!
#IBOutlet weak var pauseButton: UIButton!
#IBOutlet weak var startButton: UIButton!
#IBOutlet weak var timerTaskName: UILabel!
#IBOutlet weak var timerTimeSetting: UILabel!
var timerTask: TaskData?
var timerTime: TaskData?
var seconds = 100
var timer = Timer()
var isTimerRunning = false
var resumeTapped = false
#IBAction func cancel(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
#IBAction func startButtonTapped(_ sender: Any) {
if isTimerRunning == false {
runTimer()
self.startButton.isEnabled = false
}
}
func runTimer() {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(ViewController.updateTimer)), userInfo: nil, repeats: true)
isTimerRunning = true
pauseButton.isEnabled = true
}
#IBAction func pauseButtonTapped(_ sender: UIButton) {
if self.resumeTapped == false {
timer.invalidate()
self.resumeTapped = true
self.pauseButton.setTitle("Resume",for: .normal)
} else {
runTimer()
self.resumeTapped = false
self.pauseButton.setTitle("Pause",for: .normal)
}
}
#IBAction func resetButtonTapped(_ sender: Any) {
timer.invalidate()
seconds = 60
self.timerLabel.text = timeString(time: TimeInterval(seconds))
if self.resumeTapped == true {
self.resumeTapped = false
self.pauseButton.setTitle("Pause",for: .normal)
}
isTimerRunning = false
pauseButton.isEnabled = false
startButton.isEnabled = true
}
func updateTimer() {
if seconds < 1 {
timer.invalidate()
//Send alert to indicate "time's up!"
} else {
seconds -= 1
timerLabel.text = timeString(time: TimeInterval(seconds))
}
}
func timeString(time:TimeInterval) -> String {
let hours = Int(time) / 3600
let minutes = Int(time) / 60 % 60
let seconds = Int(time) % 60
return String(format:"%02i:%02i:%02i", hours, minutes, seconds)
}
override func viewDidLoad() {
super.viewDidLoad()
pauseButton.isEnabled = false
if let task = timerTask {
timerTaskName.text = task.task
}
if let timerTimeLeft = timerTime {
timerTimeSetting.text = timerTimeLeft.time
}
self.timerLabel.text = timeString(time: TimeInterval(seconds))
}
}
Essentially I'm trying to get timerTimeLeft.time into my seconds variable. I've tried many different things but at I'm just stuck.

You need to add the timer to the runloop. This:
func runTimer() {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(ViewController.updateTimer)), userInfo: nil, repeats: true)
isTimerRunning = true
pauseButton.isEnabled = true
}
Should be
func runTimer() {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(ViewController.updateTimer)), userInfo: nil, repeats: true)
RunLoop.current.add(timer, forMode: .defaultRunLoopMode) // <-- Notice this
isTimerRunning = true
pauseButton.isEnabled = true
}

Related

xcode 10.1: Timer stops at 1 not 0

Yep, I have seen a few questions similar to mine but for some reason, I couldn't duplicate it! If I use == or <= with If both are giving me stop at 1. The only < gave me the 0 stops which are good, but very rare I got -1. Any help, please?
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var timeLabel: UILabel!
#IBOutlet weak var startButton: UIButton!
var timer = Timer()
var timeLeft = 10
override func viewDidLoad() {
timeLabel.text = String(10)
super.viewDidLoad()
}
#IBAction func pressTimer(_ sender: Any) {
startButton.isEnabled = false
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(startTime), userInfo: nil, repeats: true)
}
#objc func startTime() {
timeLeft -= 1
timeLabel.text = "\(timeLeft)"
if timeLeft < 0 {
startButton.isEnabled = false
self.timer.invalidate()
}
}
}
My suggestion is to declare the timer as optional and check for zero before decrementing the counter.
And set the counter to 10 in the pressTimer method
class ViewController: UIViewController {
#IBOutlet weak var timeLabel: UILabel!
#IBOutlet weak var startButton: UIButton!
var timer : Timer?
var timeLeft = 0
#IBAction func pressTimer(_ sender: Any) {
startButton.isEnabled = false
timeLeft = 10
timeLabel.text = String(timeLeft)
if timer == nil {
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(startTime), userInfo: nil, repeats: true)
}
}
#objc func startTime()
{
if timeLeft == 0 {
startButton.isEnabled = false // shouldn't it be true??
timer?.invalidate()
timer = nil
} else {
timeLeft -= 1
timeLabel.text = String(timeLeft)
}
}
}

Run Counter while button press

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

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