从 NSUserDefaults 更改为 NSCoding

Posted

技术标签:

【中文标题】从 NSUserDefaults 更改为 NSCoding【英文标题】:Changing from NSUserDefaults to NSCoding 【发布时间】:2015-05-31 20:05:39 【问题描述】:

我正在尝试创建我的第一个 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】:

您要保存的类必须符合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() 类来为每个变量添加值吗?我将如何从其他类更新游戏状态? (更新分数和声音等)谢谢 不客气。这只是我为示例制作的带有参数的初始化,您不必更改您的。您只需要实现“必需”,并确保您要加载的所有属性都在此处声明。 哦,好吧,我试试,再次感谢!对于 appdelegate 中的 toFile,我如何将其保存到正在使用的手机中?谢谢 您将其保存在您想要的位置(在这方面与 NSUserDefaults 不同)。我建议不要在缓存文件夹中(它会定期清理),最好像在NSDocumentDirectory 或任何适合您应用需求的地方一样。 好的,如果我们去聊天可以吗,因为这对我来说还是很新,我需要对我的应用程序更具体的帮助,谢谢

以上是关于从 NSUserDefaults 更改为 NSCoding的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 NSUserDefaults 和 NSDateComponent 来存储?

UITableView "cellForRowAt: indexPath" 偶尔在 Core Data 属性上调用 "init?(coder aDecoder: NSCo

仅将月份从'jan'更改为1,'feb'更改为2,'mar'更改为3 ...'dec'更改为12 [重复]

我可以随时将我的应用程序从免费更改为付费或从付费更改为免费吗?

将UIColor保存到NSUserDefaults并从NSUserDefaults加载

UIPicker 从 NSUserDefaults 中选择双值