How can you create an NSTimer in a Sprite kit game with Swift? - sprite-kit

In a Single view controller application, you can use:
Foundation.Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(GameViewController.updateFunction), userInfo: nil, repeats: true)
But, when you use that code in a Spritekit game, it comes up with errors and doesn't work.
What can I use that works?

Just start your timer like this:
class GameScene: SKScene{
var timer: Timer!
override func didMove(to view: SKView) {
timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(self.yourFunction), userInfo: nil, repeats: true)
}
#objc func yourFunction(){
print("timer function")
}
func goToAnotherScene(){
timer.invalidate()
}
}
Note that you need to set #objc before your function

I would recommend staying away from NSTimer/Timer. SpriteKit has it's own timing functions, and getting NSTimer/Timer to work bug free is a huge hassle and undertaking. Use SKAction's for 99% of your timing needs. If you provided the code, I would be better able to assist with a proper answer.

Related

Swift 5 - Timer not firing

I have the following,
class someViewController : ViewController{
var timer:Timer? = nil
override func viewDidLoad() {
timer = Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(fire), userInfo: nil, repeats: true)
}
#objc func fire(){
print("fired")
}
}
The fire function is never hit and I can't figure out why, what am I missing?
Try to clean Xcode or rebuild project, because your code works fine.

Swift timer method terminates the app early with SIGABRT error

Below is my code for having a timer change a variable from 0 to 1, which results in a SIGABRT error when the timer tries to fire:
var timerToggle = 0
let timer = Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(fireTimer), userInfo: nil, repeats: false)
#objc func fireTimer() {
timerToggle = 1
}
I know others who've had this problem seem to solve it by placing the timer declaration within the override func viewDidLoad() function but whenever I do that it gives me the following error
"Initialization of immutable value 'timer' was never used; consider replacing with assignment to '_' or removing it."
Any help would be greatly appreciated
"Initialization of immutable value 'timer' was never used; consider
replacing with assignment to '_' or removing it."
This is just a warning not an error. You can still go ahead and initialise timer in viewDidLoad.
If it is needed to activate once-fired timer in viewDidLoad, it should look somehow like the following
class MyController: UIViewController {
var timerToggle = 0
private var timer: Timer?
deinit {
timer?.invalidate()
}
#objc func fireTimer() {
timerToggle = 1
timer = nil
}
override func viewDidLoad() {
super.viewDidLoad()
timer = Timer.scheduledTimer(timeInterval: 5.0, target: self,
selector: #selector(fireTimer), userInfo: nil, repeats: false)
}
}
If you are not going to access the timer anymore simply add below to viewDidLoad
_ = Timer.scheduledTimer(timeInterval: 5.0,
target: self,
selector: #selector(fireTimer),
userInfo: nil,
repeats: false)

scheduledTimer not firing if I navigate to two viewcontrollers

I have a weak scheduledTimer:
weak var timer = Timer.scheduledTimer(timerInterval: 2.0, target: self, selector: #selector(fire), userInfo: ["id",id], repeats: false)
If I begin this timer and navigate to only one viewController, it will fire in the background with no issue. However, if I navigate to a second viewController before the timer fires, it will never go off. Any idea why this is happening?
To define
class viewController: UIViewController
{
var timer = Timer()
use in other function
func one()
{
timer = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(backClick), userInfo: ["id"], repeats: false)
}
func two()
{
timer = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(backClick), userInfo: ["id"], repeats: false)
}
inValidate() timer
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
timer.fire()
}
Because of that was weak like #Alexandr Kolesnik 's comment, or may be you invalidated when first one is disappeared.

Timer, #selector explanation

I need a timer so I used this code:
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(generalKnowledge.method), userInfo: nil, repeats: true)
But I do not understand the #selector. I tried multiple times but it doesn't work.
selector() is where you'd add in the function that you want it to call every timeInterval you set. In your example it's every second.
Do bare in mind that in Swift 4 and above, you need to add #objc before a function if you want to call it in a selector like so:
#objc func handleEverySecond() {
print("Hello world!")
}
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(handleEverySecond), userInfo: nil, repeats: true)
A selector is essentially a message that is sent to an object. It was mostly used in objective-C and Swift has tried to move away from it. However, there are still some objective-C APIs that use it, including the timer one.
This is why selectors must be marked as #objc since it needs to be exposed in order to be seen.
So when you pass a selector to the timer, you're telling it to send this message to the class when it fires.
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(action), userInfo: nil, repeats: true)
#objc func action() {
print("timer fired")
}
Also, it's important to remember that you need to keep a reference to the timer outside of the scope of the function.

NSTimer with Swift in SpriteKit able to build but crashes

I am trying to create a new NSTimer object to simply increment my counter by 1sec (To calculate the lifetime of my game) now I've seen demos and examples on how to go about this, and have done the same thing but the project continues to fail. Any suggestions to there?
This is the error message :
unrecognized selector sent to instance 0x7a83c7d0
import SpriteKit
var timerObject = NSTimer()
var count = 0
let timer = SKLabelNode(text: "0")
class GameScene: SKScene , SKPhysicsContactDelegate {
override func didMoveToView(view: SKView) {
timerObject = NSTimer.scheduledTimerWithTimeInterval( 1 , target: self , selector: Selector("result"), userInfo: nil, repeats: true)
func result(){
count++
timer.text = String(count)
}
I also wrote the function "result" as such and still crashed
func result() {
count+= 0
timer.text = "\(count)"
}
Your NSTimer callback has the wrong signature. Try this:
func result(aTimer: NSTimer!) {
count+= 0
timer.text = "\(count)"
}
I believe you'll also need to pass the selector as "result:":
timerObject = NSTimer.scheduledTimerWithTimeInterval( 1 , target: self , selector: "result:", userInfo: nil, repeats: true)
I came up with the answer for all those experiencing the same problem , it was I was experiencing the Error message: unrecognized selector sent to instance 0x7a83c7d0 well the solution is quite simple actually , I had initialized my timerObject object inside viewDidLoad more specifically the error states that the method result is not a part of gameScene
simply move the selector function of your choice underneath viewDidLoad and it should work just fine
class GameScene: SKScene , SKPhysicsContactDelegate {
var timer = NSTimer()
var count = 0
let lableTimer = SKLabelNode(text: "0")
override func didMoveToView(view: SKView) {
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "result", userInfo: nil, repeats: true)
lableTimer.position = timerPosition
lableTimer.fontSize = 40
self.addChild(lableTimer)
}
func result(){
count++
lableTimer.text = String(count)
}
Also I've moved all my initial variables inside the GameScene class rather then on top.