Using NSTimer in swift playground
First of all, your onTimer
method have to be declared as @objc
, or NSTimer
cannot find that.
As for your question, it's because you haven't started the run loop.
To do that, CFRunLoopRun()
is the simplest solution I think.
import Foundation
class MyClass {
func startTimer() {
NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: "onTimer:", userInfo: nil, repeats: true)
}
@objc func onTimer(timer:NSTimer!) {
println("Timer here")
}
}
var anInstance = MyClass()
anInstance.startTimer()
CFRunLoopRun() // <-- HERE!
For the sake of completeness, as @MartinR metioned in the comment, you can also use XCPSetExecutionShouldContinueIndefinitely()
import Foundation
import XCPlayground
XCPSetExecutionShouldContinueIndefinitely()
class MyClass {
func startTimer() {
NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: "onTimer:", userInfo: nil, repeats: true)
}
@objc func onTimer(timer:NSTimer!) {
println("Timer here")
}
}
var anInstance = MyClass()
anInstance.startTimer()
In this case the Playground runs only seconds specified in the Timeline:
NSTimer.scheduledTimerWithTimeInterval in Swift Playground
You really should not be using NSTimer
these days. It's consumes a lot of resources, causes unnecessary battery drain, and the API lends itself to ugly code.
Use dispatch_after()
instead:
dispatch_after(0, dispatch_get_main_queue()) { () -> Void in
for counter in 0...1000 {
var b = counter
}
}
Of course, since the timer will fire after playground does it's stuff you will need an equivalent of timer.fire()
to force the code to execute immediately instead of after a 0 second delay. Here's how that works:
let printFrom1To1000 = { () -> Void in
for counter in 0...1000 {
var b = counter
}
}
dispatch_after(0, dispatch_get_main_queue(), printFrom1To1000)
printFrom1To1000()
Timer does not run in Swift 3.0 playground
You need to start a run loop.
RunLoop.main.run(until: Date(timeIntervalSinceNow: 3))
The timer doesn't do anything unless there is a working run loop accepting input. The program simply ends.
Timer
reference:
Timers work in conjunction with run loops. [...] it fires only when one of the run loop modes to which the timer has been added is running and able to check if the timer’s firing time has passed.
How can I use Timer (formerly NSTimer) in Swift?
This will work:
override func viewDidLoad() {
super.viewDidLoad()
// Swift block syntax (iOS 10+)
let timer = Timer(timeInterval: 0.4, repeats: true) { _ in print("Done!") }
// Swift >=3 selector syntax
let timer = Timer.scheduledTimer(timeInterval: 0.4, target: self, selector: #selector(self.update), userInfo: nil, repeats: true)
// Swift 2.2 selector syntax
let timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: #selector(MyClass.update), userInfo: nil, repeats: true)
// Swift <2.2 selector syntax
let timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: "update", userInfo: nil, repeats: true)
}
// must be internal or public.
@objc func update() {
// Something cool
}
For Swift 4, the method of which you want to get the selector must be exposed to Objective-C, thus @objc
attribute must be added to the method declaration.
Can't get my Timer in Swift to fire in Playground
Once a source has been cancelled by dispatch_source_cancel
, it will never call its event handler again. You cannot reenable the source with dispatch_resume
after cancelling it; you must create a new source.
To make your playground work, you must remove the call to timer.cancel()
.
Furthermore, after the entire playground script has been executed, the playground process exits by default. If you want it to keep running, you need to set XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
.
So make the end of your script look like this:
var timer = Timer()
timer.tick = {
let now = NSDate()
print("\(now)")
}
timer.resume()
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
How can I make a countdown with NSTimer?
Question 1:
@IBOutlet var countDownLabel: UILabel!
var count = 10
override func viewDidLoad() {
super.viewDidLoad()
var timer = Timer.scheduledTimer(timeInterval: 0.4, target: self, selector: #selector(UIMenuController.update), userInfo: nil, repeats: true)
}
func update() {
if(count > 0) {
countDownLabel.text = String(count--)
}
}
Question 2:
You can do both. SpriteKit is the SDK you use for scene, motion, etc. Simple View Application is the project template. They should not conflict
Timer Interval not firing
The simple answer is to add this to your playground:
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
When using a playground, by default the playground runs all the code and then stops, it doesn't know to wait for the timer. This code just tells the playground to keep waiting for something to happen.
Related Topics
Retrieving Keys from Geofire Within Radius in Swift
How to Have a Swift Protocol Without Functions
How to Save and Load Arworldmap in Swiftui App
Swift - Class Method Which Must Be Overridden by Subclass
How to Benchmark Swift Code Execution
Smooth Transition Between 2 Scrollviews
Nsundomanager Casting Nsundomanagerproxy Crash in Swift Code
Why Can You Assign Non-Optional Values to Optional Types in Swift
How to Represent Magnitude for Mass in Swift
App Crashes When Trying to Append Data to a Child Value
Scene Created in Sprite Kit Level Editor Is Not Working
How to Change Gb-2312 Encoding to Utf-8
How to Change "Return" Key to "Done" on Keyboard with Swiftui