从NSUserDefaults切换到NSCoding

5
我将翻译如下:

我正在尝试创建自己的Sprite Kit Swift游戏,并使用NSUserDefaults使我的游戏数据正常工作。我想让它更加安全,所以我正在尝试转换为NSCoding。但是,我在网上找到的所有东西都没有完全帮助我,反而让我感到困惑(如果已经存在答案,很抱歉,我可能已经看过它,但不能理解。)

这是我的GameState类:

class GameState {
var score: Int
var highScore: Int
var stars: Int
var sound: Bool
var carType: Int
var xSize: Double
var ySize: Double
var gameOver: Bool

class var sharedInstance: GameState {
    struct Singleton {
        static let instance = GameState()
    }

    return Singleton.instance
}

init() {
    // Init
    score = 0
    highScore = 0
    stars = 0
    carType = 1
    sound = true
    xSize = 1
    ySize = 1
    gameOver = false

    // Load game state
    let defaults = NSUserDefaults.standardUserDefaults()

    highScore = defaults.integerForKey("highScore")
    stars = defaults.integerForKey("stars")
    sound = defaults.boolForKey("sound")
    carType = defaults.integerForKey("carType")
    xSize = defaults.doubleForKey("xSize")
    ySize = defaults.doubleForKey("ySize")
    gameOver = defaults.boolForKey("gameOver")
}


func saveState() {
    // Update highScore if the current score is greater
    highScore = max(score, highScore)

    // Store in user defaults
    let defaults = NSUserDefaults.standardUserDefaults()
    defaults.setInteger(highScore, forKey: "highScore")
    defaults.setInteger(stars, forKey: "stars")
    defaults.setBool(sound, forKey: "sound")
    defaults.setInteger(carType, forKey: "carType")
    defaults.setDouble(xSize, forKey: "xSize")
    defaults.setDouble(ySize, forKey: "ySize")
    defaults.setBool(gameOver, forKey: "gameOver")
    NSUserDefaults.standardUserDefaults().synchronize()
} }

我在其他类中使用以下方式保存和加载数据:

GameState.sharedInstance.*****

我应该如何更改这个实现NSCoding,然后从其他类中加载和保存数据?谢谢。

1个回答

2

您想要保存的类必须符合 NSCoding 协议并实现 required init(coder aDecoder: NSCoder)func encodeWithCoder(aCoder: NSCoder)

以下是一个简化的示例:

class GameState: NSObject, NSCoding {

    var score: Int?
    var gameOver: Bool?

    init(score: Int, gameOver: Bool) {
        super.init()
        self.score = score
        self.gameOver = gameOver
    }

    required init(coder aDecoder: NSCoder) {
        self.score = aDecoder.decodeObjectForKey("score") as? Int
        self.gameOver = aDecoder.decodeObjectForKey("gameOver") as? Bool
    }

    func encodeWithCoder(aCoder: NSCoder) {
        aCoder.encodeObject(self.score, forKey: "score")
        aCoder.encodeObject(self.gameOver, forKey: "gameOver")
    }

}

let myGameState = GameState(score: 42, gameOver: true)

然后您可以使用NSKeyedArchiverNSKeyedUnarchiver,例如在AppDelegate中,将您的对象保存和加载为数据:

func applicationWillTerminate(aNotification: NSNotification) {
    NSKeyedArchiver.archiveRootObject(myGameState, toFile: "a/file/path")
}

func applicationDidFinishLaunching(aNotification: NSNotification) {
    if let data = NSKeyedUnarchiver.unarchiveObjectWithFile("a/file/path") as? GameState {
        myGameState = data
    }
}

谢谢您的回复,我有几个问题:'let myGameState...'是您用来替换原始init()类以向每个变量添加值的方法吗?我该如何从其他类更新游戏状态?(例如更新分数和声音等)谢谢 - AEkon
不用客气,这只是我为了我的示例而创建的带参数的初始化函数,你不必更改你的。你只需要实现“required”并确保你想要加载的所有属性都在这里声明即可。 - Eric Aya
好的,我们去聊天吧,因为这对我来说还很新,我需要更具体的帮助来完善我的应用程序,谢谢。 - AEkon
首先请尝试这个答案,如果您还有其他问题,请在Stack Overflow上创建一个新问题。 :)建议:如果您担心修改您的代码,请先在空白项目中运行我的示例,最多只需要5分钟。然后您就可以调整您的实际代码了。如果您需要再次提问,我很乐意帮助您。 - Eric Aya
让我们在聊天中继续这个讨论 - AEkon
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接