ios 如何让函数每秒执行一次?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30090309/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 05:55:31  来源:igfitidea点击:

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

iosswiftsprite-kit

提问by Ryan Allen

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".

运行此代码后,我总是收到“无法识别的选择器发送到实例错误”。

回答by Mohammad Nurdin

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:

斯威夫特 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..")
}

回答by Shaik MD Ashiq

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

swift中有一种叫做NSTimer 的东西可以解决你的问题。我已经举了一个例子,比如如何使用它。只需根据您的目的自定义它。

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.0refers to 1 second.
  2. Change the selectorto call yourMethodName
  3. repeatsis set to trueto call that function every second.
  1. 1.0是指1秒。
  2. 更改selector为调用 yourMethodName
  3. repeats设置为true每秒调用该函数。

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

试试这个,如果你被困在某个地方,请告诉我。谢谢。

回答by Amr Angry

Swift 3

斯威夫特 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()
}

回答by Brian M

Xcode 10.2 Swift 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())

回答by Vetuka

I don't think you need NSTimerfor this.

我不认为你需要NSTimer这个。

Since you are using SpriteKit, I am going to suggest simplest solution in my opinion:

由于您使用的是 SpriteKit,因此我将建议最简单的解决方案:

Declare a variable var prevScoreCalcTime:TimeInterval = 0

声明一个变量 var prevScoreCalcTime:TimeInterval = 0

Inside of updatefunc in your GameSceneset it up like below:

updatefunc内部进行GameScene设置,如下所示:

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

Good luck!

祝你好运!

回答by Rincha

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
    }
}

回答by Pratyush Pratik

// For running a piece of code every second

// 每秒运行一段代码

///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!
}