How can I make a function execute every second in swift?

91,104

Solution 1

You can use one like this:

var timer = NSTimer()

override func viewDidLoad() {
    scheduledTimerWithTimeInterval()
}

func scheduledTimerWithTimeInterval(){
    // Scheduling timer to Call the function "updateCounting" with the interval of 1 seconds
    timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("updateCounting"), userInfo: nil, repeats: true)
}
      
func updateCounting(){
    NSLog("counting..")
}

Swift 3:

var timer = Timer()

override func viewDidLoad() {               // Use for the app's interface
    scheduledTimerWithTimeInterval()
}

override func didMove(to view: SKView) {    // As part of a game
    scheduledTimerWithTimeInterval()
}

func scheduledTimerWithTimeInterval(){
    // Scheduling timer to Call the function "updateCounting" with the interval of 1 seconds
    timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.updateCounting), userInfo: nil, repeats: true)
}

@objc func updateCounting(){
    NSLog("counting..")
}

Swift 5:

Note: this solution is compatible with iOS 10.0+.

// If needing to check for iOS compatibility use
// if #available(iOS 10.0, *) {code}

var timer = Timer()

override func viewDidLoad() {
    self.timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { _ in
        updateCounting()
    })
}

func updateCounting(){
    print("counting...")
}

You can then invalidate (stop) the timer using:

timer.invalidate()

Solution 2

There is something called NSTimer in swift which could solve your problem. I have given an example like how you can use it. Just customise it for your purpose.

var timer = NSTimer.scheduledTimerWithTimeInterval(1.0, 
                                                   target: self, 
                                                   selector: Selector("yourMethodToCall"), 
                                                   userInfo: nil, 
                                                   repeats: true)

Add this line to the place where you need to call your function repeatedly.

  1. The 1.0 refers to 1 second.
  2. Change the selector to call yourMethodName
  3. repeats is set to true to call that function every second.

Try this out and let me know if your are stuck somewhere. Thanks.

Solution 3

Swift 3

find this solution it worked for me

weak var timer: Timer?
var timerDispatchSourceTimer : DispatchSourceTimer?

func startTimer() {
    if #available(iOS 10.0, *) {
        timer = Timer.scheduledTimer(withTimeInterval: 3, repeats: true) { [weak self] _ in
            // do something here

        }

    } else {
        // Fallback on earlier versions
        timerDispatchSourceTimer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.main)
        timerDispatchSourceTimer?.scheduleRepeating(deadline: .now(), interval: .seconds(60))
        timerDispatchSourceTimer?.setEventHandler{
                // do something here

        }
        timerDispatchSourceTimer?.resume()
    }
}

func stopTimer() {
    timer?.invalidate()
    //timerDispatchSourceTimer?.suspend() // if you want to suspend timer 
    timerDispatchSourceTimer?.cancel()
}

// if appropriate, make sure to stop your timer in `deinit`
deinit {
    stopTimer()
}

Solution 4

I prefer

var timer: Timer?

override func viewDidLoad() {
    super.viewDidLoad()          

    timer =  Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { (timer) in                
        // Do what you need to do repeatedly         
    }
}

To stop it:

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    if timer != nil {
        timer?.invalidate()
        timer = nil
    }
}

Solution 5

Xcode 10.2 Swift 5:

override func viewDidLoad() {
    super.viewDidLoad()
    // ...
    Timer.scheduledTimer(timeInterval: 8.0, target: self, selector: Selector(("your @obcj func name")), userInfo: nil, repeats: true)
}

//Anywhere in the same view controller to stop the loop:
Timer.cancelPreviousPerformRequests(withTarget: your @obcj func name())
Share:
91,104
Ryan Allen
Author by

Ryan Allen

Updated on October 16, 2021

Comments

  • Ryan Allen
    Ryan Allen over 2 years

    I want to add a score to the top of my scene in the game I am working on. The score is going to based on how long you last, and will increase every second. Thanks for the help in advance!

    import SpriteKit
    
    class easyScene: SKScene {
        let scrollBarEasyBottom = SKSpriteNode(imageNamed: "scrollBarEasyBottom")
        let scrollBarEasyTop = SKSpriteNode(imageNamed: "scrollBarEasyTop")
        let ball = SKSpriteNode(imageNamed: "ball")
        var origSBEBpositionX = CGFloat(0)
        var origSBETpositionX = CGFloat(0)
        var maxSBEBX = CGFloat(0)
        var SBEBSpeed = 5
        var maxSBETX = CGFloat(0)
        var SBETSpeed = 5
        var score = 0
        var timer: NSTimer?
        
        var scoreText = SKLabelNode(fontNamed: "Kailasa")
        
        override func didMoveToView(view: SKView) {
            println("Easy Scene is the location")
            self.backgroundColor = UIColor.blackColor()
            self.scrollBarEasyBottom.position = CGPoint(x:0, y:270)
            self.addChild(self.scrollBarEasyBottom)
            self.scrollBarEasyBottom.yScale = 0.2
            self.origSBEBpositionX = self.scrollBarEasyBottom.position.x
            // end scrollBarEasyBottom
            self.scrollBarEasyTop.position = CGPoint(x:20, y:400)
            self.addChild(self.scrollBarEasyTop)
            self.scrollBarEasyTop.yScale = 0.2
            self.origSBETpositionX = self.scrollBarEasyTop.position.x
            // end scrollBarEasyTop
            self.ball.position = CGPoint(x:40, y:293)
            self.addChild(self.ball)
            self.ball.yScale = 0.17
            self.ball.xScale = 0.17
            // end ball
            self.maxSBEBX = self.scrollBarEasyBottom.size.width - self.frame.size.width
            self.maxSBEBX *= -1
            self.maxSBETX = self.scrollBarEasyTop.size.width - self.frame.size.width
            self.maxSBETX *= -1
            //
            self.scoreText.text = "0"
            self.scoreText.fontSize = 60
            self.scoreText.position = CGPoint(x: CGRectGetMidX(self.frame), y: 500)
            self.scoreText.text = String(self.score)
            self.addChild(self.scoreText)
            timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("scoreIncrease") , userInfo: nil, repeats: true)
            func scoreIncrease (){
                score++
                println(score)
            }
        }
    
        override func update(currentTime: NSTimeInterval) {
            if self.scrollBarEasyBottom.position.x <= maxSBEBX + 1200 {
                self.scrollBarEasyBottom.position.x = self.origSBEBpositionX
            }
            if self.scrollBarEasyTop.position.x <= maxSBETX + 1200 {
                self.scrollBarEasyTop.position.x = self.origSBETpositionX
            }
            
            scrollBarEasyBottom.position.x -= CGFloat(self.SBEBSpeed)
            scrollBarEasyTop.position.x -= CGFloat(self.SBETSpeed)
            // moving bars
            var degreeRotation = CDouble(self.SBEBSpeed) * M_PI / 180
            self.ball.zRotation -= CGFloat(degreeRotation)
            //rotate ball
        }        
    }
    

    After running this code, I always get an

    unrecognized selector sent to instance error