web-dev-qa-db-fra.com

Comment puis-je faire en sorte qu'une fonction s'exécute chaque seconde rapidement?

Je veux ajouter un score au sommet de ma scène dans le jeu sur lequel je travaille. Le score sera basé sur votre temps de vie et augmentera chaque seconde. Merci pour l'aide à l'avance!

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


    }


    }

Après avoir exécuté ce code, je reçois toujours un "sélecteur non reconnu envoyé à une erreur d'instance".

45
Ryan Allen

Vous pouvez en utiliser un comme ceci:

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..")
}
77
Mohammad Nurdin

Il y a quelque chose qui s'appelle NSTimer dans Swift) qui pourrait résoudre votre problème. J'ai donné un exemple de la façon dont vous pouvez l'utiliser. Personnalisez-le en fonction de vos besoins.

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

Ajoutez cette ligne à l'endroit où vous devez appeler votre fonction à plusieurs reprises.

  1. Le 1.0 fait référence à 1 seconde.
  2. Changez le selector pour appeler votreMethodName
  3. repeats est défini sur true pour appeler cette fonction toutes les secondes.

Essayez ceci et laissez-moi savoir si vous êtes coincé quelque part. Merci.

29
Shaik MD Ashiq

Swift 3

trouver cette solution cela a fonctionné pour moi

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()
}
8
Amr Angry

Je ne pense pas que vous ayez besoin de NSTimer pour cela.

Puisque vous utilisez SpriteKit, je vais suggérer la solution la plus simple à mon avis:

Déclarer une variable var prevScoreCalcTime:TimeInterval = 0

Dans update func dans votre GameScene, configurez-le comme ci-dessous:

override func update(_ currentTime: TimeInterval) {
    if currentTime - prevScoreCalcTime > 1 {
        prevScoreCalcTime = currentTime
        // Any function you put here will execute every second
    }
}

Bonne chance!

2
sc13

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)

}// end of viewDidLoad


//Anywhere in the same view controller to stop the loop:
Timer.cancelPreviousPerformRequests(withTarget: your @obcj func name())
2
Brian M

// Pour exécuter un morceau de code toutes les secondes

///Runs every second, to cancel use: timer.invalidate()
@discardableResult public static func runThisEvery(
    seconds: TimeInterval,
    startAfterSeconds: TimeInterval,
    handler: @escaping (CFRunLoopTimer?) -> Void) -> Timer {
    let fireDate = startAfterSeconds + CFAbsoluteTimeGetCurrent()
    let timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, fireDate, seconds, 0, 0, handler)
    CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, CFRunLoopMode.commonModes)
    return timer!
}
0
Pratyush Pratik

Je préfère

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

//Your params

timer =  Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { (timer) in

          //use your params

}
0
Rincha