Iterate For Loop Overtime in Swift - ios

How can I iterate a for loop overtime in swift? A typical loop will execute immediately as fast as possible. However, I would like to expand the time in which the loop occurs.
Say I have the following loop:
for var i = 0; i < 4; i+=1{
print(i)
}
And I wanted this loop to occur over a span of 1 second, each iteration taking 0.25 seconds. How could I do this? Thanks for any help

You might want to create a Timer like this:
timer = NSTimer.scheduledTimerWithTimeInterval(0.25, target: self, selector: #selector(MyClass.tic), userInfo: nil, repeats: true)
time.fire() //first time
this timer will call the function selected with #selector when it fires, and will fire every 0.25 secondes (first parameter) until you invalidate it. So when you have ended your loops you can
call timer.invalidate()
tic() is a function you can define, and can have any name you want:
func tic() {
numberOfTimeFired = numberOfTimeFired + 1
print(numberOfTimeFired)
}
In Swift 3 the timer declaration would be:
timer = Timer.scheduledTimer(timeInterval: 0.25, target: self, selector: #selector(MyClass.tic), userInfo: nil, repeats: true)

Related

Scheduled timers in SpriteKit

I have scheduled timers that add sprite nodes to the screen as obstacles
func timers(){
personTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(spawnPerson), userInfo: nil, repeats: true)
bikeTimer = Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(spawnBike), userInfo: nil, repeats: true)
motorcycleTimer = Timer.scheduledTimer(timeInterval: 2.5, target: self, selector: #selector(spawnMotorcycle), userInfo: nil, repeats: true)
}
I added a function to invalidate those timers. so that a bonus "level" can be ran.
func invalidateTimers(){
// Obstacles
personTimer.invalidate()
bikeTimer.invalidate()
motorcycleTimer.invalidate()
}
When the bonus is called
func bonus() {
invalidateTimers()
bonusTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(spawnDiamonds), userInfo: nil, repeats: true)
}
The problem that I'm having is that when the bonus is done running I invalidate the bonusTimer and recall timers(). But when I do all the timers in the function seem to be firing twice. Whats an easy workaround for that since they can't just be paused.
Instead of using timers, consider using SKActions, as they work well with SpriteKit. To start the timer, run:
let wait1 = SKAction.wait(forDuration: 1)
let personTimer = SKAction.repeatForever(SKAction.sequence([wait1, SKAction.run {
spawnPerson() // spawnBike() etc. for each different timer
}]))
self.run(personTimer, withKey: "spawnPerson")
with modified wait values and function calls for each different timer. Then to stop the timer, run:
self.removeAction(forKey: "spawnPerson")
for each action using a different key.
Instead of using timers, you can use update: method of your SKScene subclass. It calls once per frame and has currentTime parameter. So you can easily calculate time intervals you need and trigger corresponding methods.

Refresh label every second

I try to make a refresh for a label every second in swift 3.
I alway get the following error:
Showing Recent Issues
Command failed due to signal: Segmentation fault: 11
This is the Code I've used:
var TimerBeacon = Timer.scheduledTimer(timeInterval: 1, target: self,
selector: Selector(("Timer")), userInfo: nil, repeats: true)
func Timer() {
//here is the label to refresh
}
I hope someone could help me :)
It looks like your code isn't updated for Swift 3, and could use some better naming conventions.
Create the timer:
let timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(update), userInfo: nil, repeats: true)
This is the function that the timer will call every second:
func update() {
// here is the label to refresh
}
When you want to stop the timer, call invalidate():
timer.invalidate()
You can achieve the same without timer. Use the following code
var iteration = 0
func updateLabel() {
iteration = iteration == Int.max ? 0 : (iteration + 1)
DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
self.label.text = "\(self.iteration)"
self.updateLabel()
})
}
}
Note that I have taken iteration just for example. You can update the label the way you want.

NSTimer/Timer duration and UI update

Probably a simple question, however, I can't seem to conceive an elegant approach.
I want to design a trivial application that allows a timer to be set to a duration (say 1 minute), after that duration the timer should expire, in the duration the timer should update the UI every second.
Thus if the timer is set to one minute, the timer should fire, update the UI every second (by calling a method) and then finally invalidate after 1 minute.
My conundrum is, I can set a scheduledTimerWithInterval, it calls a method on the timer interval. If I make this 1 minute I can call a method after one minute to invalidate the timer, but there doesn't seem to be a mechanism to perform calls during this minute.
Can you give me some guidance?
I would have done something like this:
1: Declare a timer and a counter:
var timer = Timer()
var counter = 0
2: Create a new function called for example startEverySecond that starts the timer with one second interval, this function is called after 60 seconds and will be called for 1 minute and then invalidate:
func startEverySecond() {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(everySecond), userInfo: nil, repeats: true)
}
func everySecond(){
if counter == 60{
timer.invalidate()
}
counter = counter + 1
print("Second")
}
3: Handle the start and stop of the timer:
// Start with 60 second interval
timer = Timer.scheduledTimer(timeInterval: 60, target: self, selector: #selector(startEverySecond), userInfo: nil, repeats: false)
// Stop
timer.invalidate()
So basically when you start your timer it will start off with 60 seconds and when this is done it will call the function startEverySecondand this will change the timer to call the everySecondfunction every second for 1 minute. To stop the timer just call timer.invalidate()
Swift 3.x code
Make two global variables
var seconds = 1
var secondTimer:Timer?
Then make these two functions
// for setup of timer and variable
func setTimer() {
seconds = 1
secondTimer?.invalidate()
secondTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateUI), userInfo: nil, repeats: true)
}
//method to update your UI
func updateUI() {
//update your UI here
//also update your seconds variable value by 1
seconds += 1
if seconds == 60 {
secondTimer?.invalidate()
secondTimer = nil
}
print(seconds)
}
finally call setTimer() wherever you want

Type 'GameScene has no member 'delay'

I declared delay and it is giving me an error, I am trying to slow down the timer.
//Updates Timer
func updateTimer() {
var delay: Int
seconds += 1
self.timerLabel.text = String(self.seconds * 0.01)
timer = NSTimer.scheduledTimerWithTimeInterval(-2.0, target: self, selector: #selector(GameScene.delay), userInfo: nil, repeats: false)
The message is telling you that there is no selector for GameScene.delay. You need a func that matches this name. Note that because you have used "GameScene" rather than "gameScene", it may be a class, in which case you would need a "class func" called delay. However, more likely is you would want "self.delay" to be called. ie. one of
func delay(timer: NSTimer) { ... }
class func delay(timer: NSTimer) { ... }
Also, what are you trying to achieve with "-2.0"? You can't run a timer in the past - if will default to 0.1 if <= 0.
the selector portion of a NSTimer is meant to run a function so you declare the function then the timer should be placed outside of the function instead of inside the function
func updateTimer() {
var delay: Int
seconds += 1
self.timerLabel.text = String(self.seconds * 0.01)}
let timer = NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: #selector(self.updateTimer), userInfo: nil, repeats: false)
also could you be more specific when you say you are trying to slow down the timer so

Simple NSTimer implementation issue

I have just started to learn swift 2 and I am testing a few things in an Xcode 'playground'. When a create an instance of the 'pyx' (below) I am not seeing the console output I would expect. I am sure I have made a silly mistake but after staring at it for a while I cannot figure it out.
class zxy {
var gameTimer = NSTimer()
var counter = 0
init() {
gameTimer = NSTimer (timeInterval: 1, target: self, selector: "Run:", userInfo: nil, repeats: true)
}
func Run(timer : NSTimer) {
while(counter < 10){
print(counter)
counter++
}
timer.invalidate()
}
}
Thanks in advanced.
You have 2 problems with your code. As #glenstorey points out in his answer, you need to call the method scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:, not the init method you're calling.
EDIT:
As #DanBeauleu says in his comment to my answer, the call would look like this in Swift:
NSTimer.scheduledTimerWithTimeInterval(
1,
target: self,
selector: "Run:",
userInfo: nil,
repeats: true)
The second problem is your Run method.
You don't want a while loop. That will repeat 10 times in a tiny fraction of a second the first time the timer fires, then invalidate the timer.
Your timer method needs to be changed like this:
func Run(timer : NSTimer)
{
if counter < 10
{
print(counter)
counter++
}
else
{
timer.invalidate()
}
}
(BTW, by strong convention, method/function names should start with a lower-case letter, so your Run function should be named run instead.)
You've created a NSTimer object, but that doesn't start the timer - just gets it ready to go. Use scheduledTimerWithTimeInterval to create and start the timer.

Resources