0

I am having a problem decoding an object after I encode it in Swift.

Here is my class:

class Player: NSObject, NSCoding {

    var score:Int = 0

init(difficulty: Int!) {
    super.init()

}


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

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

Here is when I am encoding and decoding:

let data = NSKeyedArchiver.archivedDataWithRootObject(player)
let newPlayer = NSKeyedUnarchiver.unarchiveObjectWithData(data) as Player

It crashes everytime when I try to unarchive it. Anybody have any reasons why?

P.S. I have no idea why my code isn't formatted. I have it indented 4 spaces over! Sorry about that!

dhint4
  • 1,132
  • 2
  • 11
  • 25

3 Answers3

1

Here is what I did to get it working:

  1. Created an instance of player in my App Delegate
  2. You can call this anywhere if your application UIApplication.sharedApplication().player
dhint4
  • 1,132
  • 2
  • 11
  • 25
0

This should work. I will post a separate answer if you wish to save an array of Player objects.

Two NSObject classes:

import Foundation

class Player: NSObject {

    var score:Int = 0

    func encodeWithCoder(aCoder: NSCoder!) {
        aCoder.encodeInteger(score, forKey: "score")
    }

    init(coder aDecoder: NSCoder!) {
        score = aDecoder.decodeIntegerForKey("score")
    }

    override init() {
    }
}

class ArchivePlayer:NSObject {

    var documentDirectories:NSArray = []
    var documentDirectory:String = ""
    var path:String = ""

    func savePlayer(#player: Player) {
        documentDirectories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
        documentDirectory = documentDirectories.objectAtIndex(0) as String
        path = documentDirectory.stringByAppendingPathComponent("players.archive")

        if NSKeyedArchiver.archiveRootObject(player, toFile: path) {
            println("Success writing to file!")
        } else {
            println("Unable to write to file!")
        }
    }

    func retrievePlayer() -> NSObject {
        var dataToRetrieve = Player()
        documentDirectories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
        documentDirectory = documentDirectories.objectAtIndex(0) as String
        path = documentDirectory.stringByAppendingPathComponent("players.archive")
        if let dataToRetrieve2 = NSKeyedUnarchiver.unarchiveObjectWithFile(path) as? Player {
            dataToRetrieve = dataToRetrieve2 as Player
        }
        return(dataToRetrieve)
    }
}

And then in the ViewController:

import UIKit

class ViewController: UIViewController {

    var player = Player()

    override func viewDidLoad() {
        super.viewDidLoad()

        player.score = 22
        ArchivePlayer().savePlayer(player: player)
        let playerToRetrieve = ArchivePlayer().retrievePlayer() as Player
        println(playerToRetrieve.score)
    }
}

This demonstrates archiving and unarchiving to file. Printing "Success writing to file!" to demonstrate the archiving. Printing the stored object player.score to demonstrate unarchiving.

Steve Rosenberg
  • 19,348
  • 7
  • 46
  • 53
  • Thank you for both of your answers. I instead created an instance of player in my App Delegate and called used using UIApplication.sharedApplication().player – dhint4 Sep 25 '14 at 21:07
0

For storing arrays of Player objects here are the NSObject classes:

import Foundation

class Player: NSObject {

    var score:Int = 0

    func encodeWithCoder(aCoder: NSCoder!) {
        aCoder.encodeInteger(score, forKey: "score")
    }

    init(coder aDecoder: NSCoder!) {
        score = aDecoder.decodeIntegerForKey("score")
    }

    override init() {
    }
}

class ArchivePlayer:NSObject {

    var documentDirectories:NSArray = []
    var documentDirectory:String = ""
    var path:String = ""

    func savePlayerArray(#playerArray: [Player]) {
        documentDirectories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
        documentDirectory = documentDirectories.objectAtIndex(0) as String
        path = documentDirectory.stringByAppendingPathComponent("playersArray.archive")

        if NSKeyedArchiver.archiveRootObject(playerArray, toFile: path) {
            println("Success writing to file!")
        } else {
            println("Unable to write to file!")
        }
    }

    func retrievePlayerArray() -> NSObject {
        var dataToRetrieve = [Player]()
        documentDirectories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
        documentDirectory = documentDirectories.objectAtIndex(0) as String
        path = documentDirectory.stringByAppendingPathComponent("playersArray.archive")
        if let dataToRetrieve2 = NSKeyedUnarchiver.unarchiveObjectWithFile(path) as? [Player] {
            dataToRetrieve = dataToRetrieve2
        }
        return(dataToRetrieve)
    }
}

Here is the ViewController:

import UIKit

class ViewController: UIViewController {

    var player1 = Player()
    var player2 = Player()
    var player3 = Player()
    var playerArchiveArray = [Player]()

    override func viewDidLoad() {
        super.viewDidLoad()


        player1.score = 12
        player2.score = 22
        player3.score = 32
        playerArchiveArray = [player1, player2, player3]
        ArchivePlayer().savePlayerArray(playerArray: playerArchiveArray)
        var playerRetrieveArray = ArchivePlayer().retrievePlayerArray() as [Player]

        for player in playerRetrieveArray {
            println(player.score)
        }
    }
}
Steve Rosenberg
  • 19,348
  • 7
  • 46
  • 53