NSCoding 游戏数据未快速保存

Posted

技术标签:

【中文标题】NSCoding 游戏数据未快速保存【英文标题】:NSCoding gamedata not saved swift 【发布时间】:2015-04-24 09:57:50 【问题描述】:

目前,我的数据没有在另一个新会话中检索到,它使用默认值。我必须有一个现有的 plist 文件才能工作吗?我尝试使用现有文件,但没有成功。

我按照这里的指南http://battleofbrothers.com/sirryan/saving-game-data-in-spritekit

class GameData : NSObject, NSCoding 

/// Data to save

var variableC : Int = 3

/// Create of shared instance

class var sharedInstance: GameData 

    struct Static 
        static var instance: GameData?
        static var token: dispatch_once_t = 0
    

    dispatch_once(&Static.token) 
        var gamedata = GameData()
        if let savedData = GameData.loadGame() 
            gamedata = savedData
        
        Static.instance = gamedata
    

    return Static.instance!


override init() 
    super.init()


required init(coder: NSCoder) 
    super.init()


func encodeWithCoder(coder: NSCoder) 
    coder.encodeObject(GameData.sharedInstance, forKey: "GameData")


class func loadGame() -> GameData? 
    // load existing high scores or set up an empty array
    let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
    let documentsDirectory = paths[0] as! String
    let path = documentsDirectory.stringByAppendingPathComponent("GameData.plist")
    let fileManager = NSFileManager.defaultManager()

    // check if file exists
    if !fileManager.fileExistsAtPath(path) 
        // create an empty file if it doesn't exist
        println("File doesn't exist")
        if let bundle = NSBundle.mainBundle().pathForResource("DefaultFile", ofType: "plist") 
            fileManager.copyItemAtPath(bundle, toPath: path, error:nil)
        
    

    if let rawData = NSData(contentsOfFile: path) 
        // do we get serialized data back from the attempted path?
        // if so, unarchive it into an AnyObject, and then convert to an array of HighScores, if possible
        if let data = NSKeyedUnarchiver.unarchiveObjectWithData(rawData) as? GameData 
            println("We loaded the data!")
            return data
        
    
    println("we returned Nil")
    return nil


func save() 
    // find the save directory our app has permission to use, and save the serialized version of self.scores - the HighScores array.
    let saveData = NSKeyedArchiver.archivedDataWithRootObject(GameData.sharedInstance);
    let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray;
    let documentsDirectory = paths.objectAtIndex(0)as! NSString;
    let path = documentsDirectory.stringByAppendingPathComponent("GameData.plist");

    saveData.writeToFile(path, atomically: true);

我用这个在init函数中加载游戏数据

var gameData: GameData = GameData.sharedInstance

更新数据

    gameData.variableC = gameData.variableC + 1
    gameData.save()
    println(gameData.variableC)

【问题讨论】:

【参考方案1】:

您保存数据但不在您的初始化中使用它。在initWithCoder:

required init(coder: NSCoder) 
        super.init()
        GameData.shaderInstance = coder.decodeObjectForKey("GameData")
    

【讨论】:

【参考方案2】:

就像 Jozsef 说的,我忘了解码数据。但是,我需要解码每个单独的变量,然后将其复制到 GameData 以使其工作。

这里是

class GameData : NSObject, NSCoding 

/// Data to save

var variableC : Int! = 3

/// Create of shared instance

class var sharedInstance: GameData 

    struct Static 
        static var instance: GameData?
        static var token: dispatch_once_t = 0
    

    dispatch_once(&Static.token) 
        var gamedata = GameData()
        if let savedData = GameData.loadGame() 
            gamedata.variableC = savedData.variableC
        
        Static.instance = gamedata
    

    return Static.instance!


override init() 
    super.init()


required init(coder: NSCoder) 
    super.init()
    self.variableC = coder.decodeObjectForKey("variableC") as? Int



func encodeWithCoder(coder: NSCoder) 
    coder.encodeObject(GameData.sharedInstance.variableC, forKey: "variableC")


class func loadGame() -> GameData? 
    // load existing high scores or set up an empty array
    let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
    let documentsDirectory = paths[0] as! String
    let path = documentsDirectory.stringByAppendingPathComponent("GameData.plist")
    let fileManager = NSFileManager.defaultManager()

    // check if file exists
    if !fileManager.fileExistsAtPath(path) 
        // create an empty file if it doesn't exist
        println("File doesn't exist")
        if let bundle = NSBundle.mainBundle().pathForResource("DefaultFile", ofType: "plist") 
            fileManager.copyItemAtPath(bundle, toPath: path, error:nil)
        
    

    if let rawData = NSData(contentsOfFile: path) 
        // do we get serialized data back from the attempted path?
        // if so, unarchive it into an AnyObject, and then convert to an array of HighScores, if possible
        if let data = NSKeyedUnarchiver.unarchiveObjectWithData(rawData) as? GameData 
            println("We loaded the data!")
            return data
        
    
    return nil


func save() 
    // find the save directory our app has permission to use, and save the serialized version of self.scores - the HighScores array.
    let saveData = NSKeyedArchiver.archivedDataWithRootObject(GameData.sharedInstance);
    let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray;
    let documentsDirectory = paths.objectAtIndex(0)as! NSString;
    let path = documentsDirectory.stringByAppendingPathComponent("GameData.plist");

    saveData.writeToFile(path, atomically: true);

【讨论】:

以上是关于NSCoding 游戏数据未快速保存的主要内容,如果未能解决你的问题,请参考以下文章

使用 NSCoding 保存结构

为啥 NSCoding 无法在正确保存后解码对象?

iCloud - NSCoding 或核心数据

Swift 中 SKProduct 的 NSCoding 错误

从 NSUserDefaults 更改为 NSCoding

Swift,NSCoding 保存类的数组不起作用