Initialising String with += expression returns "()" - ios

Start of app (Main storyboard but it's fine in simulator to.)
After clicking play button in mutates into something that isn't a 1,2,3....
Here is the code in the viewcontroller and it's not much. Pretty simple stopwatch app.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var timeLabel: UILabel!
var counter = 0
var clock : Timer = Timer()
override func viewDidLoad() {
timeLabel.text = String(counter)
super.viewDidLoad()
// 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.
}
#IBAction func playButton(_ sender: Any) {
clock = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateTimer), userInfo: nil, repeats: true)
}
func updateTimer(){
timeLabel.text = String(describing: counter += 1)
}
#IBAction func pauseButton(_ sender: Any) {
clock.invalidate()
}
#IBAction func resetButton(_ sender: Any) {
clock.invalidate()
counter = 0
timeLabel.text = String(counter)
}
}
I've tried setting constraints but that just shoots out "ambiguous" warnings all over the place. Any suggestions? Ideas?

The problem is at your updateTimer method. You need to move your variable increment to the line above and then create a string representation from the variable:
func updateTimer() {
counter += 1
timeLabel.text = String(counter)
}

Related

How to show the exact time with my Stopwatch?

I've recently been working on making a Stopwatch app that is similar to the one on the stock iOS devices. I have the timer working but I would like it to follow the same look and exact time like the stopwatch Apple has. As of right now I have it just showing the seconds. For what I know there has to be some kind of to convert the numbers to the 00:00.00 format.
import UIKit
class ViewController: UIViewController {
var counter = 0
var timer = Timer()
#IBOutlet weak var timerLbl: UILabel!
#IBAction func startBtn( sender: Any) {
timer.invalidate()
timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(ViewController.updateTimer), userInfo: nil, repeats: true)
}
#IBAction func stopBtn( sender: Any) {
timer.invalidate()
counter = 0
}
func updateTimer() {
counter += 1
timerLbl.text = "(counter)"
}
override func viewDidLoad() {
super.viewDidLoad()
// 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.
}
}
You should create a reference date when you create the timer, and then every time the timer fires, get the current time by creating a date, and then get the time between the two dates using a calendar. You can get more information about how to do that here

call array items with a delay using in swift - get UIResponder error

Searching around didn't seem to provide anything that I understood straight away.
I'm trying to make a stupid 'old skool' loading screen for an app which will print out 'DOS like' statements.
My current code looks like this, but I get a UIResponder, UIApplicationDelegate error - EXE_BAD_ACCESS
I've tried copying this to a new project etc. still get the same error.
Code below:
class ViewController: UIViewController {
#IBOutlet weak var loadingLBL: UILabel!
#IBOutlet weak var logoIMG: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//fades logo image in
logoIMG.alpha = 0
UIView.animateWithDuration(5, animations: {
self.logoIMG.alpha = 1;
})
//array for loading text
var loading = ["Loading please wait.......\n", "Registry , OK!\n", `"Available ram, 256k\n", "BIOS Load... OK\n", "Welcome" ]`
var i = 0
var str: String = ""
var timer = NSTimer()
//delay function for loading array text
func delayFunc() {
str += "\(loading[i])\n"
loadingLBL.text = str
if i == loading.count - 1 {
timer.invalidate()
}
i += 1
}
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector(delayFunc()), userInfo: nil, repeats: true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
As I mentioned, I get a crash and I've no idea what I've done wrong.
Any help would be much appreciated.
I think your problem is that delayFunc() is in viewDidLoad, the selector is looking in the viewController but can't find the function (because it is in viewDidLoad)
Edit: I wasn't 100% clear about why the selector can't find delayFunc when it's in viewDidLoad. If you declare a function within another function's body it's lifetime is at most the lifetime of its 'parent' function. So when your timer tries to call delayFunc, delayFunc doesn't exist anymore because viewDidLoad has finished running.
Try:
var i = 0
var str: String = ""
var timer = NSTimer()
var loading = ["Loading please wait.......\n", "Registry , OK!\n", "Available ram, 256k\n", "BIOS Load... OK\n", "Welcome" ]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//fades logo image in
logoIMG.alpha = 0
UIView.animateWithDuration(5, animations: {
self.logoIMG.alpha = 1;
})
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "delayFunc", userInfo: nil, repeats: true)
}
func delayFunc() {
str += "\(loading[i])\n"
loadingLBL.text = str
if i == loading.count - 1 {
timer.invalidate()
}
i += 1
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}

SIGABRT error in Xcode 7

I'm having trouble compiling this code in Swift successfully. Its a program for stopwatch. Two labels(start and stop) and a textfield as the output. It says its a delegate problem and highlights this in red:
class AppDelegate: UIResponder, UIApplicationDelegate
My code for the project is as follows:
import UIKit
class ViewController: UIViewController {
var timer = NSTimer()
var counter = 1
#IBOutlet weak var Label: UILabel!
override func viewDidLoad()
{
super.viewDidLoad()
// 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.
}
func updateCounter()
{
counter += 1
Label.text = String(counter)
}
#IBAction func Start(sender: AnyObject)
{
counter = 0
Label.text = String(counter)
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector ("updateCounter"), userInfo: nil, repeats: true)
}
#IBAction func Stop(sender: AnyObject)
{
timer.invalidate()
}
}
Very common problem, here's what you have to do:
Go through every outlet on your storyboard and delete it.
Reconnect every function in your ViewController to the outlets.
The problem, I believe, is that you have changed the name of an outlet in your code, and when the storyboard looks for that outlet it crashes your app. Make sure that when you rename your outlets, you reconnect it too!

How to stop NSTimer.scheduledTimerWithTimeInterval

How do i stop my timer from running? Not like a pause, but a stop.
import UIKit
class LastManStandingViewController: UIViewController {
#IBOutlet weak var timeLabel: UILabel!
#IBOutlet weak var timeTextbox: UITextField!
#IBOutlet weak var startButton: UIButton!
#IBOutlet weak var stopButton: UIButton!
var myCounter = 0
var myTimer : NSTimer = NSTimer()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
timeLabel.text = String(myCounter)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func startTimer(){
myTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("updateTimer"), userInfo: nil, repeats: true)
println("func startTimer")
}
func stopTimer(){
myTimer.invalidate()
myCounter = 0
timeLabel.text = String(myCounter)
println("func stopTimer")
}
func updateTimer(){
timeLabel.text = String(myCounter++)
println("func updateTimer")
}
#IBAction func startButton(sender: AnyObject) {
startTimer()
}
#IBAction func stopButton(sender: AnyObject) {
stopTimer()
}
}
I can start the timer, but when i press the Stop button, it reset itself, and starts counting again. It doesn't stop.
Made it work. Something was buggy with my project! Fixed it by removing the button and re-adding them. Looks like i had a duplicate or something.
You don't have to use Selector:
#IBAction func startButton(sender: AnyObject) {
myTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "updateTimer:", userInfo: nil, repeats: true)
}
Also, the timer passes itself to the selected method, so you can invalidate it inside the method if you need:
func updateTimer(timer: NSTimer) {
timeLabel.text = String(Counter++)
timer.invalidate()
}
Or if the timer is an instance variable:
myTimer.invalidate()
myTimer = nil
It's a good thing to nil the instance variable timer after having invalidated it, it avoids further confusion if you need to create another timer with the same variable. Also, method names and variables should begin with a lowercase letter.
Screenshot to show the timer invalidated and set to nil.
Update for Swift 2.2+
See https://stackoverflow.com/a/36160191/2227743 for the new #selector syntax replacing Selector().
you can use this when some condition is met and you want to stop timer:
Timer.invalidate()
Here is simple example :
func UpdateTimer(){
timeLabel.text = String(Counter++)
if timeLabel.text == String("5") {
Timer.invalidate()
}
}
this will stop timer.
You can modify it as per your need.
As pre Swift 2.2
let printTimer = NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: #selector(printDescription), userInfo: nil, repeats: true)
func printDescription() {
print("Print timer will print every after 2.0 seconds")
}
Print timer will print every after 2.0 seconds

access dictionary for use within a countdown in SWIFT

I have a working countdown which you can increase by pushing the add button and thats what the time counts down from (so basically a user can set the countdown)
I would like to display the starting time as 00:00 as it does in my label.
When I click button to increase the countdown it just begins at 1 obviously because at the moment its just an Int
So i had a thought of create a dictionary something like this
var timeDictionary : [Double : Double] = [00 : 00]
I just want to increase to 00:01, 2, 3 when the + button is pressed and start from 00:00. Can anyone help with this if possible please?
this is my full code for the countdown
var timeDictionary : [Double : Double] = [00 : 00]
var timer = NSTimer()
var countdown = 0
func runTimer() {
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self,
selector:Selector("updateTimer"), userInfo: nil, repeats: true)
}
func updateTimer() {
if countdown > 0 {
countdown--
TimerLabel.text = String(countdown)
} else {
countdown = 0
TimerLabel.text = String(countdown)
}
}
#IBOutlet weak var TimerLabel: UILabel!
#IBAction func IncreaseCountdown(sender: AnyObject) {
countdown++
TimerLabel.text = String(countdown)
}
#IBAction func StartCountdown(sender: AnyObject) {
runTimer()
}
#IBAction func StopCountdown(sender: AnyObject) {
timer.invalidate()
}
override func viewDidLoad() {
super.viewDidLoad()
// 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.
}
}
The simplest approach is just to format the counter as you display it -
#IBOutlet weak var timerLabel: UILabel!
var timer = NSTimer()
var countdown = 0
func runTimer() {
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector:Selector("updateTimer"), userInfo: nil, repeats: true)
}
func updateTimer() {
if --countdown < 1 {
timer.invalidate()
countdown=0;
}
self.updateTimerLabel();
}
#IBAction func IncreaseCountdown(sender: AnyObject) {
countdown++
self.updateTimerLabel()
}
#IBAction func StartCountdown(sender: AnyObject) {
runTimer()
}
#IBAction func StopCountdown(sender: AnyObject) {
timer.invalidate()
}
func updateTimerLabel() {
TimerLabel.text =NSString(format:"%02d:%02d",seconds/60,seconds%60)
}
}
Note that I also changed TimerLabel to timerLabel as the convention is that variables should start with a lowercase letter

Resources