Как я могу заставить функцию выполняться каждую секунду в swift?
Я хочу добавить счет в начало моей сцены в игре, над которой я работаю. Счет будет зависеть от того, как долго вы продержитесь, и будет увеличиваться каждую секунду. Спасибо за помощь в продвижении!
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
}
}
После запуска этого кода я всегда получаю "нераспознанный селектор, отправленный на ошибку экземпляра".
5 ответов
Вы можете использовать один из них:
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..")
}
Свифт 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..")
}
Есть что-то под названием NSTimer в swift, которое может решить вашу проблему. Я привел пример того, как вы можете его использовать. Просто настройте его для своих целей.
var timer = NSTimer.scheduledTimerWithTimeInterval(1.0,
target: self,
selector: Selector("yourMethodToCall"),
userInfo: nil,
repeats: true)
Добавьте эту строку в место, где вам нужно повторно вызывать вашу функцию.
1.0
относится к 1 секунде.- Изменить
selector
позвонить yourMethodName repeats
установлен вtrue
вызывать эту функцию каждую секунду.
Попробуйте это и дайте мне знать, если вы застряли где-то. Благодарю.
Свифт 3
найти это решение у меня сработало
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()
}
Я предпочитаю
if timer != nil
{
timer?.invalidate()
timer = nil
}
//Your params
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { (timer) in
//use your params
}
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())
Я не думаю что тебе нужно NSTimer
за это.
Поскольку вы используете SpriteKit, я собираюсь предложить самое простое на мой взгляд решение:
Объявить переменную var prevScoreCalcTime:TimeInterval = 0
Внутри update
Функ в вашем GameScene
установить как показано ниже:
override func update(_ currentTime: TimeInterval) {
if currentTime - prevScoreCalcTime > 1 {
prevScoreCalcTime = currentTime
// Any function you put here will execute 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!
}