在按下主页按钮时暂停 NSTimer,并在应用程序处于前台后再次启动它们
Pause NSTimer on home-button-press and start them again once the app is in foreground
我一直在寻找一种解决方案,以便在用户 "tabs down" 游戏时暂停我的 SpriteKit 游戏。到目前为止,我找到了一个使用 SKAction
而不是 NSTimer
的解决方案,只要操作之间的时间保持不变,它就可以工作。但是,我的NSTimer
的速度发生了变化。所以我需要找到另一个解决方案。
我有一堆 NSTimer
位于 GameScene -> didMoveToView
NSTimer.scheduledTimerWithTimeInterval(0.2, target: self, selector: Selector("SpawnBullets"), userInfo: nil, repeats: true)
NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("SpawnMeteors"), userInfo: nil, repeats: true)
NSTimer.scheduledTimerWithTimeInterval(timeInterval, target: self, selector: Selector("onTimer:"), userInfo: nil, repeats: true)
现在,我该如何在应用程序进入后台时简单地暂停它们?
编辑:添加了我的时间间隔增加速度功能
func onTimer(timer: NSTimer) {
var goodTimes = time / 20
if (goodTimes > 1.8){
goodTimes = 1.8
}
timer.fireDate = timer.fireDate.dateByAddingTimeInterval(timeInterval - goodTimes)
self.runAction(SKAction.sequence([SKAction.runBlock(SpawnRocks), SKAction.waitForDuration(goodTimes / 2), SKAction.runBlock(SpawnPowerUp)]))
}
NSTimer
的暂停不是 objective-c 或 swift 的原生功能。为了解决这个问题,您需要创建一个扩展,我恰好创建了这个扩展并将与您分享。这将适用于 OS X 和 iOS
import Foundation
import ObjectiveC
#if os(iOS)
import UIKit
#else
import AppKit
#endif
private var pauseStartKey:UInt8 = 0;
private var previousFireDateKey:UInt8 = 0;
extension NSTimer
{
private var pauseStart: NSDate!{
get{
return objc_getAssociatedObject(self, &pauseStartKey) as? NSDate;
}
set(newValue)
{
objc_setAssociatedObject(self, &pauseStartKey,newValue,objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN);
}
}
private var previousFireDate: NSDate!{
get{
return objc_getAssociatedObject(self, &previousFireDateKey) as? NSDate;
}
set(newValue)
{
objc_setAssociatedObject(self, &previousFireDateKey,newValue,objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN);
}
}
func pause()
{
pauseStart = NSDate();
previousFireDate = self.fireDate;
self.fireDate = NSDate.distantFuture() ;
}
func resume()
{
if(pauseStart != nil)
{
let pauseTime = -1 * pauseStart.timeIntervalSinceNow;
let date = NSDate(timeInterval:pauseTime, sinceDate:previousFireDate );
self.fireDate = date;
}
}
}
然后当你需要使用它时,只需调用 timer.pause()
和 timer.resume()
你当然必须在你的游戏场景对象中跟踪你的计时器才能做到这一点,所以确保 timer
是整个 class 可访问的变量,在制作计时器时,您需要 timer = NSTimer.schedule...
在你的开头 class:
var spawnBulletsTimer : NSTimer?;
var spawnMeteorsTimer : NSTimer?;
var onTimer: NSTimer?;
创建计时器时:
spawnBulletsTimer = NSTimer.scheduledTimerWithTimeInterval(0.2, target: self, selector: Selector("SpawnBullets"), userInfo: nil, repeats: true)
spawnMeteorsTimer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("SpawnMeteors"), userInfo: nil, repeats: true)
onTimer = NSTimer.scheduledTimerWithTimeInterval(timeInterval, target: self, selector: Selector("onTimer:"), userInfo: nil, repeats: true)
然后需要暂停的时候:
onTimer?.pause()
spawnBulletsTimer?.pause()
spawnMeteorTimer?.pause()
那么当你需要恢复时:
onTimer?.resume()
spawnBulletsTimer?.resume()
spawnMeteorTimer?.resume()
我一直在寻找一种解决方案,以便在用户 "tabs down" 游戏时暂停我的 SpriteKit 游戏。到目前为止,我找到了一个使用 SKAction
而不是 NSTimer
的解决方案,只要操作之间的时间保持不变,它就可以工作。但是,我的NSTimer
的速度发生了变化。所以我需要找到另一个解决方案。
我有一堆 NSTimer
位于 GameScene -> didMoveToView
NSTimer.scheduledTimerWithTimeInterval(0.2, target: self, selector: Selector("SpawnBullets"), userInfo: nil, repeats: true)
NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("SpawnMeteors"), userInfo: nil, repeats: true)
NSTimer.scheduledTimerWithTimeInterval(timeInterval, target: self, selector: Selector("onTimer:"), userInfo: nil, repeats: true)
现在,我该如何在应用程序进入后台时简单地暂停它们?
编辑:添加了我的时间间隔增加速度功能
func onTimer(timer: NSTimer) {
var goodTimes = time / 20
if (goodTimes > 1.8){
goodTimes = 1.8
}
timer.fireDate = timer.fireDate.dateByAddingTimeInterval(timeInterval - goodTimes)
self.runAction(SKAction.sequence([SKAction.runBlock(SpawnRocks), SKAction.waitForDuration(goodTimes / 2), SKAction.runBlock(SpawnPowerUp)]))
}
NSTimer
的暂停不是 objective-c 或 swift 的原生功能。为了解决这个问题,您需要创建一个扩展,我恰好创建了这个扩展并将与您分享。这将适用于 OS X 和 iOS
import Foundation
import ObjectiveC
#if os(iOS)
import UIKit
#else
import AppKit
#endif
private var pauseStartKey:UInt8 = 0;
private var previousFireDateKey:UInt8 = 0;
extension NSTimer
{
private var pauseStart: NSDate!{
get{
return objc_getAssociatedObject(self, &pauseStartKey) as? NSDate;
}
set(newValue)
{
objc_setAssociatedObject(self, &pauseStartKey,newValue,objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN);
}
}
private var previousFireDate: NSDate!{
get{
return objc_getAssociatedObject(self, &previousFireDateKey) as? NSDate;
}
set(newValue)
{
objc_setAssociatedObject(self, &previousFireDateKey,newValue,objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN);
}
}
func pause()
{
pauseStart = NSDate();
previousFireDate = self.fireDate;
self.fireDate = NSDate.distantFuture() ;
}
func resume()
{
if(pauseStart != nil)
{
let pauseTime = -1 * pauseStart.timeIntervalSinceNow;
let date = NSDate(timeInterval:pauseTime, sinceDate:previousFireDate );
self.fireDate = date;
}
}
}
然后当你需要使用它时,只需调用 timer.pause()
和 timer.resume()
你当然必须在你的游戏场景对象中跟踪你的计时器才能做到这一点,所以确保 timer
是整个 class 可访问的变量,在制作计时器时,您需要 timer = NSTimer.schedule...
在你的开头 class:
var spawnBulletsTimer : NSTimer?;
var spawnMeteorsTimer : NSTimer?;
var onTimer: NSTimer?;
创建计时器时:
spawnBulletsTimer = NSTimer.scheduledTimerWithTimeInterval(0.2, target: self, selector: Selector("SpawnBullets"), userInfo: nil, repeats: true)
spawnMeteorsTimer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("SpawnMeteors"), userInfo: nil, repeats: true)
onTimer = NSTimer.scheduledTimerWithTimeInterval(timeInterval, target: self, selector: Selector("onTimer:"), userInfo: nil, repeats: true)
然后需要暂停的时候:
onTimer?.pause()
spawnBulletsTimer?.pause()
spawnMeteorTimer?.pause()
那么当你需要恢复时:
onTimer?.resume()
spawnBulletsTimer?.resume()
spawnMeteorTimer?.resume()