Ios Timer Start Again After Invalidate

Working with Timers in Swift


Aasif Khan

Past  | December vii, 2021 5:02 pm  |4-min read

Timers are super handy in Swift, from creating repeating tasks to scheduling work with a filibuster. This tutorial explains how to create a timer in Swift.

We'll discuss how to use the Timer course, formerly known equally NSTimer, to schedule timers. We'll get into repeating and non-repeating timers, using run loops, keeping track of timers, and how you can reduce their free energy and ability impact.

Creating a repeating timer in Swift is surprisingly elementary. Here'south how:

let timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(fire), userInfo: nil, repeats: true)

@objc func fire()
{
print("Burn!!!")
}

In the above code, a few things happen:

  • A timer is created using the Timer.scheduledTimer(…) class method. Its return value is assigned to the constant timer. This constant now contains a reference to the timer, which will come up in handy after on.
  • The parameters of scheduledTimer() are the timer interval of 1 second, which uses a mechanism known as target-action, some userInfo that'south set to nil, and the parameter repeats ready to truthful.
  • Nosotros've too coded a function fire(). This is the function that's called when the timer fires, i.east. roughly every 2nd. Past setting target to self and selector to #selector(burn) you're indicating that whenever the timer fires, the function fire() of self needs to be called.

The to a higher place code should run in a class context, for instance in a view controller class. The fire() role is function of the course, and self refers to the current course instance.

You can besides create a timer using a closure. Like this:

allow timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { timer in
print("Fire!!!")
})

In the in a higher place code, the last parameter cake takes a closure. The closure has 1 parameter, the timer itself.

The timer with target-action and self won't work in an Xcode playground, unless yous create a class or struct. Hither's the code you lot can use to create a timer in a playground in Xcode:

import PlaygroundSupport

PlaygroundPage.electric current.needsIndefiniteExecution = true

let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { timer in
print("Burn down!!!")
PlaygroundPage.electric current.finishExecution()
})

In the above lawmaking, nosotros're setting needsIndefiniteExecution to true so the playground won't automatically finish running when the playground is finished. The timer is able to fire this way, and at that point nosotros call finishExecution() to halt the playground.

Thank you to abaft-closure syntax we can brand that closure-based timer fifty-fifty more concise. Like this:

let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in
print("Burn down!!!")
}

See how the last argument label is omitted? That'southward because the terminal parameter is a closure. It makes the code more concise. Neat!

The @objc attribute makes the fire() role available in Objective-C. The Timer class is part of the Objective-C runtime, so that'due south why we need that @objc attribute.

In the previous example, nosotros've used v parameters to create a timer. They are:

  • timeInterval: the interval betwixt timer fires in seconds, its blazon is Double
  • target: a course instance that the part for selector should be called on, often self
  • selector: the function to call when the timer fires, with #selector(…)
  • userInfo: a dictionary with data that's provided to the selector, or nil
  • repeats: whether this timer is repeating or non-repeating

Creating a non-repeating timer is as uncomplicated as setting the repeats parameter to imitation. The timer will just fire once and immediately invalidate itself after.

Then how do yous end a repeating timer? It's simple. Here'due south how:

timer.invalidate()

Y'all'd keep rail of the timer variable somewhere, for example through a stored holding on the form that you're using the timer in. You lot can then use that property to manage the timer.

Yous tin can also attach some extra information to a timer past using userInfo. This value is sent to the part that fires, via its timer parameter. Here's an example:

let timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(fire(timer:)), userInfo: ["score": 10], repeats: true)

@objc func fire(timer: Timer)
{
if allow userInfo = timer.userInfo as? [String: Int],
let score = userInfo["score"] {

print("You scored \(score) points!")
}
}

In the above lawmaking, nosotros've added the dictionary ["score": 10] to the timer. When it fires, this dictionary is passed to the burn down(timer:) office as timer.userInfo. Inside the fire(timer:) part we're checking if the userInfo holding has the type nosotros expect, and nosotros get the right value.

Allow'south look at a applied instance for using timers, next.

Imagine yous're creating a game. The user has 60 seconds to solve a puzzle and score points. As the count down timer runs out, you're keeping runway of how many seconds are left.

Start, we're creating two properties at the height of our game class. Something like:

var timer:Timer?
var timeLeft = 60

The timer doesn't start immediately. Until it starts, the timer belongings is nix. At some betoken the game has started, then nosotros likewise starting time the timer:

timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(onTimerFires), userInfo: zip, repeats: truthful)
The timer calls onTimerFires() every second, indefinitely. And here's that part:

@objc func onTimerFires()
{
timeLeft -= 1
timeLabel.text = "\(timeLeft) seconds left"

if timeLeft <= 0 { timer?.invalidate() timer = naught } } Every time the timer fires information technology subtracts i from timeLeft, and it updates the "time left" label. When the timer reaches nada, timer is invalidated and prepare to goose egg. This will effectively create a countdown timer that counts down from 60 to zero. And at a bespeak in the time to come, you can of class reset the countdown and get-go again.

Timers work in conjunction with run loops. Run loops are a fundamental role of threads and concurrency.

Information technology'south easiest to imagine run loops similar a ferris wheel. People tin can enter a passenger car and get moved effectually by the bike. In a like fashion, you can schedule a chore on a run loop. The run loop keeps "looping" and executing tasks. When in that location are no tasks to execute, the run loop waits or quits.

The way run loops and timers work together, is that the run loop checks if a timer should fire. A timer isn't a existent-time mechanism, because the firing of the timer can coincide with the runloop already executing another task. You can compare this to wanting to enter the ferris cycle when there's no car yet at the bottom entrance. The result is that a timer can fire later than it's scheduled.

This isn't necessarily a bad thing. Don't forget yous're running lawmaking on a mobile device that has free energy and power constraints! The device can schedule run loops more efficiently to salvage power.

You can also assist the arrangement save power by using a timer property called tolerance. This will tell the scheduling organization: "Await, I want this to run every second, just I don't intendance if it'due south 0.2 seconds too late." This of course depends on your app. Apple tree recommends to set up the tolerance to at least 10% of the interval time for a repeating timer.

Here'southward an case:

let timer = Timer.scheduledTimer(timeInterval: one.0, target: self, selector: #selector(fire), userInfo: nil, repeats: truthful)
timer.tolerance = 0.two

The tolerance property uses the same units every bit the timeInterval holding, then the higher up code will use a tolerance of 200 milliseconds.

The tolerance volition never crusade a timer to fire early, only later. And the tolerance will neither cause a timer to "drift", i.eastward. when one timer fire is too late, it won't affect the scheduled time of the next timer fire.

When using the Timer.scheduledTimer(…) class method, the timer is automatically scheduled on the current run loop in the default style. This is typically the run loop of the main thread. Equally a result, timers may not fire when the run loop on the principal thread is busy, for example when the user of your app is interacting with the UI.

You lot tin solve this by manually scheduling the timer on a run loop yourself. Here's how:

permit timer = Timer(timeInterval: i.0, target: cocky, selector: #selector(burn down), userInfo: zippo, repeats: truthful)

RunLoop.current.add(timer, forMode: .commonModes)

The outset line of code volition create an instance of Timer using the Timer(…) initializer. The second line of code adds the timer to the current run loop using the .commonModes input fashion. In short, this tells the run loop that the timer should be checked for all "common" input modes, which effectively lets the timer burn during the interaction with UI.

By the fashion, a common source for frustration is accidentally using the Timer(…) initializer when you wanted to employ the Timer.scheduledTimer(…) to create a timer. If y'all use the sometime, the timer won't fire until you've added information technology to a run loop! And you lot'll pull your hair out, because you lot're certain you lot've scheduled the timer correctly…

A mutual scenario in practical iOS development is executing some code with a small filibuster. It's easiest to utilise K Central Acceleration for that purpose, and not use a Timer.

The following lawmaking executes a chore on the main thread with a 300 millisecond delay:

DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300)) {
print("BOOYAH!")
}

Information technology's more concise than using Timer. And because you're only running it once, in that location's no demand to keep track of a timer anyhow.

And then, at present you know! When yous need your code run in a timely manner, Timer is a tool you can depend on. Requite or take 😉

Create Your App Now

Happy Holidays

App Builder

cochraneponjuseme.blogspot.com

Source: https://www.appypie.com/timer-swift-how-to

0 Response to "Ios Timer Start Again After Invalidate"

Publicar un comentario

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel