Unexpected Output: I am using the below code to print out the timer according to the button pressed but timer is starting with 20 only. what's wrong? - ios

import UIKit
class ViewController: UIViewController {
let eggTimes = ["Soft": 60,"Medium": 72,"Hard": 95]
var secondsRemaining = 20
var timer = Timer()
#IBAction func hardnessSelected(_ sender: UIButton) {
let hardness = sender.currentTitle!
var secondsRemaining = eggTimes[hardness]!
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true)
}
#objc func timerAction()
{
if secondsRemaining > 0 {
print("\(secondsRemaining) seconds")
secondsRemaining -= 1
}
}
}
Unexpected Output: I am using the below code to print out the timer according to the button pressed but timer is starting with 20 only. what's wrong?

You are creating a new variable inside your Button function:
var secondsRemaining = eggTimes[hardness]!
instead you should assing your value. It should be:
self.secondsRemaining = eggTimes[hardness]!

Related

Unable to solve the "Thread 1: breakpoint 1.1 (1)" error is Swift

I am writing a code to implement a time which is fairly simple. But for some reason I'm getting a Thread breakpoint and a blue (lldb) in the debug console, which doesn't tell me what the problem is. Here's my code:
import UIKit
class ViewController: UIViewController {
var eggTimes = ["Soft":3, "Medium":5, "Hard":7]
var totalTime = 0
var progress: Float = 0.0;
var passedTime = 0
var timer = Timer()
#IBAction func hardnessSelected(_ sender: UIButton) {
//timer.invalidate()
totalTime = eggTimes[sender.currentTitle!]!
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self,selector: #selector(updateTimer), userInfo: nil, repeats: true)
}
#objc func updateTimer() {
if totalTime > 0
{
print(totalTime)
totalTime-=1
}
}
}

Can't get timer to count down

I'm trying to learn how to use a timer in Swift, and every solution I look up is broken somehow or beyond my understanding.
I've tried with a closure, and without.
With a closure, I can actually get the app to run without crashing, but the timer just repeats 60, it doesn't count down and I don't know why.
let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { timer in
var secondsRemaining = 60
print(secondsRemaining)
secondsRemaining -= 1
})
I've also tried using an #objc func with selector, but my app crashes right away with error Thread 1: "-[__SwiftValue countdown]: unrecognized selector sent to instance 0x600002970e40" (I haven't even gotten to trying the count down yet).
class ViewController: UIViewController {
let timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(countdown), userInfo: nil, repeats: true)
#objc func countdown() {
print("fire")
}
…
…
}
Any help is appreciated.
EDIT
If I place my variable outside the block, I get an error inside the block Instance member 'secondsRemaining' cannot be used on type 'ViewController'
class ViewController: UIViewController {
var secondsRemaining = 60
let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { timer in
print(secondsRemaining)
secondsRemaining -= 1
})
}
But if I create a new project and put the timer inside viewDidLoad(), it works. I don't know why.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var secondsRemaining = 60
let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { timer in
print(secondsRemaining)
secondsRemaining -= 1
})
}
}
Every time your timer fires, a new variable with an initial value of 60 is instantiated, thus always printing 60.
You have to declare your counting variable outside:
private var secondsRemaining = 60
let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { timer in
print(self.secondsRemaining)
self.secondsRemaining -= 1
})
Or:
class ViewController: UIViewController {
private var secondsRemaining = 60
let timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(countdown), userInfo: nil, repeats: true)
#objc func countdown() {
print("fire")
self.secondsRemaining -= 1
}
}
You're declaring counter inside the timer call. That's why every time the timer executes it resets the counter to 60 seconds. You need to declare your timer outside the it's call:
var secondsRemaining = 60
let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { timer in
print(secondsRemaining)
secondsRemaining -= 1
})
As mentioned in the comments above, don't reset the variable every single time you get in the closure and change you timer to the following. Create a simple obj function to do whatever logic you want. Also name your functionalists meaningfully
class XViewController: UIViewController {
private var secondsRemaining:Int = 60
let timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(startScrolling), userInfo: nil, repeats: true)
#objc func startScrolling() {
print(secondsRemaining)
secondsRemaining -= 1
}
}
Here is the fixed code:
class ViewController: UIViewController {
private var secondsRemaining = 60
override func viewDidLoad() {
super.viewDidLoad()
let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { timer in
print(secondsRemaining)
secondsRemaining -= 1
})
}
}

Swift 2 - Timed Actions one second apart?

I'm trying to get output like so:
1 (then a one second delay)
Hello
2 (then a one second delay)
Hello
3 (then a one second delay)
Hello
But instead I get
1
2
3 (then a one second delay)
Hello
Hello
Hello
Here's my for loop invoking the NSTimer
var timer = NSTimer()
for i in 1...3 {
print("\(i)");
timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(MainVPScreenViewController.printTest), userInfo: nil, repeats: false)
}
And here's the selector method:
func printTest() {
print("Hello")
}
Thanks in advance for any help you can provide
Try this solution without NSTimer:
var i = 1
func printHello() {
print(i)
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
print("Hello")
i +=1
if i <= 3 {
printHello()
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
printHello()
}
I need 2 NSTimers to do this, this is my approach
class ViewController: UIViewController {
var i = 1
override func viewDidLoad() {
super.viewDidLoad()
beginPrinting()
}
func beginPrinting() {
var timer2 = NSTimer()
if(i <= 100)
{
timer2 = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(self.printWithDelay), userInfo: nil, repeats: false)
}
}
func printWithDelay()
{
var timer = NSTimer()
print("\(i)");
i += 1
timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(self.printTest), userInfo: nil, repeats: false)
}
func printTest() {
print("Hello")
beginPrinting()
}
}
Hope this helps you
Use timer with repeat to true. So in your view controller would be like this
var timer = NSTimer()
var counter = 0
var max = 10
let delay = 1 // in second
override func viewDidLoad() {
super.viewDidLoad()
timer = NSTimer.scheduledTimerWithTimeInterval(delay, target: self,
selector: #selector(self.printTest), userInfo: nil, repeats: true)
}
func printTest() {
counter += 1
print(counter)
print(hello)
if counter == maxNumber {
timer.invalidate()
}
}
This does it with repeat false, and is set up to be in a playground:
import XCPlayground
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
#objc class Foo: NSObject {
static var timer = NSTimer()
var i:Int
override init() {
Foo.timer = NSTimer()
i = 1
}
func schedule() {
print("\n\(i)");
i += 1
Foo.timer = NSTimer.scheduledTimerWithTimeInterval(1.0,
target: self,
selector: #selector(printTest),
userInfo: nil,
repeats: false)
}
#objc func printTest() {
print("Hello")
if i < 5 {
schedule()
}
}
}
let bar = Foo()
bar.schedule()

IOS swift countdown timer will not stop

I am attempting to make a countdown timer that counts down from 60 seconds and then stops when it gets to 0. But for the timer keeps going into negative seconds. Any advice is appreciated. Code:
#IBOutlet var timeCounter: UILabel!
var second = 60
var timer = NSTimer()
var timerRunning = true
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
setTimer()
timerCounting()
}
func setTimer(){
second -= 1
timeCounter.text = "\(second)"
}
func timerCounting(){
if(timerRunning == true){
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("setTimer"), userInfo: nil, repeats: true)
timerRunning = true
if second == 0 {
timerRunning = false
timer.invalidate()
}
}
}
You have to move the invalidation into the setTimer function since at its current location will never be triggered because timerCounting is only called once - in the beginning.
func setTimer(){
second -= 1
timeCounter.text = "\(second)"
if second == 0 {
timerRunning = false
timer.invalidate()
}
}
play with this in playground
import XCPlayground
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
import Foundation
#objc class C:NSObject {
var timer: NSTimer?
var second = 5
func setTimer(){
if c.second < 0 {
print("the timer fires the last time here ...")
timer?.invalidate()
} else {
print(second)
second -= 1
}
}
}
let c = C()
func timerCounting(){
c.timer = NSTimer.scheduledTimerWithTimeInterval(1, target: c, selector: Selector("setTimer"), userInfo: nil, repeats: true)
}
timerCounting()

Reference a variable value inside an #IBAction function from another class in Swift

I'm trying to make a laundry timer app in Swift where the washer and drying will have different starting times, counting down to 0.
func updateTime() {
...
var elapsedTime: NSTimeInterval = operationDuration - (currentTime - startTime)
...
}
In the var elapsedTime I have operationDuration (how long the washer or dryer will take) and later on in the #IBAction func for pressing the "washer" button I have
let operationDuration == 1800
However I am getting an error the the updateTime func that
'operationDuration' is not defined.
How can I do this? Thanks in advance.
edit:
Here is my washerButtonPress code:
#IBAction func washerButtonPress(sender: AnyObject) {
// TODO: start 30 minute countdown
if !timer.valid {
var operationDuration = 1800
let aSelector:Selector = "updateTime"
timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: aSelector, userInfo: nil, repeats: true)
startTime = NSDate.timeIntervalSinceReferenceDate()
}
And how I'm trying to call it in my func updateTime()
var elapsedTime: NSTimeInterval = washerButtonPress.operationDuration - (currentTime - startTime)
and it returns '(AnyObject) -> ()' does not have a member named 'operationDuration'
I apologize for not knowing much but I'm pretty new to this
If this is merely a constant, you can declare it as a global variable.
let kOperationDuration = 1800
class Washer {
...
#IBAction func washerButtonPress(sender: AnyObject) {
if !timer.valid {
let aSelector:Selector = "updateTime"
timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: aSelector, userInfo: nil, repeats: true)
startTime = NSDate.timeIntervalSinceReferenceDate()
}
}
...
}
Then in the Dryer class you can reference the constant.
class Dryer {
...
func updateTime() {
...
var elapsedTime: NSTimeInterval = kOperationDuration - (currentTime - startTime)
...
}
...
}

Resources