swift - 按 home 按钮时暂停 NSTimer,并在应用程序位于前台后再次启动它们

标签 swift sprite-kit nstimer

我一直在寻找一种解决方案,以便在用户“按下 Tab 键”游戏时暂停我的 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() 您当然必须在您的gamescene 对象来执行此操作,因此请确保 timer 是整个类都可以访问的变量,并且在创建计时器时,您需要 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()

关于swift - 按 home 按钮时暂停 NSTimer,并在应用程序位于前台后再次启动它们,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34383852/

相关文章:

objective-c - iOS Sprite Kit 如何在横向方向上使弹丸指向目标?

iphone - iOS 系统时间更新导致 NSTimer/NSDate funkiness

ios - 如何在 swift 中使用 segue 发送用户信息以查看 Controller ?

ios - 仅将 subview 添加到当前 View 的 UINavigationBar

ios - 显示来自模型的警报

ios - Swift:去除 Spritekit 中不同场景的广告

swift - 覆盖变量中的值

swift - 关于Swift的自制touches功能的问题

iphone - 对 NSCFTimer 感到困惑...它是什么?

Cocoa:对象在不应该自动释放的时候被自动释放