0

I have tried look at the other answers regarding NSUserDefaults, but so far they haven't helped.

I'm trying to save a Player into NSUserDefaults, but the Player class also has two variables for the custom classes Pokemon and Items.

How do I save and load the player? Do I need to separately encode each custom class variable and decode them as well? I'm not sure how it would work.

Here are my classes: Player Class

import Foundation
class Player : NSCoder {

    private var steps = Int()
    private var money = Int()
    private var items = [Item]()
    private var pokemon = [Pokemon]()
    var eggArray = [Int]()

    struct User {
        static var Gold = Player()
    }

    override init(){
        steps = 0
        money = 0
        items = [Item]()
        pokemon = [Pokemon]()
        eggArray = [1, 4, 7, 10, 13, 16, 19, 21, 23, 27, 29, 32, 37, 41, 43, 43, 46, 48, 50, 52, 54, 56, 58, 60, 60, 63, 66, 69, 72, 74, 77, 79, 79, 81, 83, 84, 86, 88, 90, 92, 95, 96, 98, 100, 102, 104, 108, 109, 111, 113, 114, 115, 116, 118, 120, 122, 123, 127, 128, 129, 131, 133, 133, 133, 133, 133, 137, 138, 140, 142, 143, 147, 152, 155, 158, 161, 163, 165, 167, 170, 172, 173, 174, 175, 177, 179, 183, 185, 187, 190, 191, 193, 194, 198, 200, 201, 202, 203, 204, 206, 207, 209, 211, 213, 214, 215, 216, 218, 220, 222, 223, 225, 226, 227, 228, 231, 234, 235, 236, 236, 236, 238, 239, 240, 241, 246]
    }

    init(steps: Int, money: Int, items: [Item], pokemon: [Pokemon], eggArray: [Int]){
        self.steps = steps
        self.money = money
        self.items = items
        self.pokemon = pokemon
        self.eggArray = eggArray
    }

    required convenience init(coder aDecoder: NSCoder) {
        let steps = aDecoder.decodeIntegerForKey("steps")
        let money = aDecoder.decodeIntegerForKey("money")
        let items = aDecoder.decodeObjectForKey("items") as! [Item]
        let pokemon = aDecoder.decodeObjectForKey("pokemon") as! [Pokemon]
        let eggArray = aDecoder.decodeObjectForKey("eggArray") as! [Int]
        self.init(steps: steps, money: money, items: items, pokemon: pokemon, eggArray: eggArray)
    }

    func encodeWithCoder(aCoder: NSCoder) {
        aCoder.encodeInteger(steps, forKey: "steps")
        aCoder.encodeInteger(money, forKey: "money")
        aCoder.encodeObject(items, forKey: "items")
        aCoder.encodeObject(pokemon, forKey: "pokemon")
        aCoder.encodeObject(eggArray, forKey: "eggArray")
    }

}

Item Class

import Foundation
import CoreData

class Item : NSObject{

    var name : String
    var price : Int


    init(item: NSManagedObject){
        name = item.valueForKey("name") as! String
        price = item.valueForKey("price") as! Int

        super.init()

    }

    init(name: String, price: Int){
        self.name = name
        self.price = price

        super.init()

    }

}

Pokemon Class

import Foundation
import SwiftyJSON

class Pokemon : NSObject {

    var dexNo = Int()
    var name = String()

    var type1 = String()
    var type2 = String()

    var hp = Int()
    var atk = Int()
    var def = Int()
    var spatk = Int()
    var spdef = Int()
    var spd = Int()

    var move1 = String()
    var move2 = String()
    var move3 = String()
    var move4 = String()

    var evolves = String()
    var method = String()
    var detail = String()

    var happiness = Int()
    var MAXHAPPINESS = Int()

    var currentEXP = Double()
    var MAXEXP = Double()
    var level = Double()

    var isEgg = Bool()
    var stepsToHatch = Int()

    override init(){

    }

    init(jsonNumber: Int){
        let path : String = NSBundle.mainBundle().pathForResource("PKMNdata", ofType: "json") as String!
        let jsonData = NSData(contentsOfFile: path) as NSData!
        let readableJSON = JSON(data: jsonData, options: NSJSONReadingOptions.MutableContainers, error: nil)

        currentEXP = 0
        MAXEXP = 1000000
        level = 1

        happiness = 0
        MAXHAPPINESS = 255

        isEgg = true
        stepsToHatch = 10000

        self.dexNo = readableJSON["Pokemon"]["Pokemon\(jsonNumber)"]["DEXNO"].int!
        self.name = readableJSON["Pokemon"]["Pokemon\(jsonNumber)"]["NAME"].string!
        self.type1 = readableJSON["Pokemon"]["Pokemon\(jsonNumber)"]["TYPE1"].string!
        self.type2 = readableJSON["Pokemon"]["Pokemon\(jsonNumber)"]["TYPE2"].string!
        self.evolves = readableJSON["Pokemon"]["Pokemon\(jsonNumber)"]["EVOLVES"].string!
        self.method = readableJSON["Pokemon"]["Pokemon\(jsonNumber)"]["METHOD"].string!
        self.detail = readableJSON["Pokemon"]["Pokemon\(jsonNumber)"]["DETAIL"].string!
        self.hp = readableJSON["Pokemon"]["Pokemon\(jsonNumber)"]["HP"].int!
        self.atk = readableJSON["Pokemon"]["Pokemon\(jsonNumber)"]["ATK"].int!
        self.def = readableJSON["Pokemon"]["Pokemon\(jsonNumber)"]["DEF"].int!
        self.spatk = readableJSON["Pokemon"]["Pokemon\(jsonNumber)"]["SPATK"].int!
        self.spdef = readableJSON["Pokemon"]["Pokemon\(jsonNumber)"]["SPDEF"].int!
        self.spd = readableJSON["Pokemon"]["Pokemon\(jsonNumber)"]["SPD"].int!
        self.move1 = readableJSON["Pokemon"]["Pokemon\(jsonNumber)"]["MOVE1"].string!
        self.move2 = readableJSON["Pokemon"]["Pokemon\(jsonNumber)"]["MOVE2"].string!
        self.move3 = readableJSON["Pokemon"]["Pokemon\(jsonNumber)"]["MOVE3"].string!
        self.move4 = readableJSON["Pokemon"]["Pokemon\(jsonNumber)"]["MOVE4"].string!

    }

    init(dexNo: Int, name: String, type1: String, type2: String, evolves: String, method: String, detail: String, hp: Int, atk: Int, def: Int, spatk: Int, spdef: Int, spd: Int, move1: String, move2: String, move3: String, move4: String){
        currentEXP = 0
        MAXEXP = 1000000
        level = 1

        happiness = 0
        MAXHAPPINESS = 255

        isEgg = true
        stepsToHatch = 10000

        self.dexNo = dexNo
        self.name = name
        self.type1 = type1
        self.type2 = type2
        self.evolves = evolves
        self.method = method
        self.detail = detail
        self.hp = hp
        self.atk = atk
        self.def = def
        self.spatk = spatk
        self.spdef = spdef
        self.spd = spd
        self.move1 = move1
        self.move2 = move2
        self.move3 = move3
        self.move4 = move4
    }

}

and the two buttons I am using to call save and load (for testing only) there's a global variable: var userDefaults = NSUserDefaults.standardUserDefaults() if it matters.

@IBAction func savePlayer(sender: UIButton) {
    print("save")
    userDefaults = NSUserDefaults.standardUserDefaults()
    let encodedData = NSKeyedArchiver.archivedDataWithRootObject(Player.User.Gold)
    userDefaults.setObject(encodedData, forKey: "player")
    userDefaults.synchronize()
}


@IBAction func loadPlayer(sender: UIButton) {
    print("load")
    let decoded  = userDefaults.objectForKey("player") as! NSData
    let decodedPlayer = NSKeyedUnarchiver.unarchiveObjectWithData(decoded) as! Player
    Player.User.Gold = decodedPlayer
}

Right now I get an error when saving, which I assume is for the saving the item and Pokemon variables in the Player class.

1 Answer 1

2

Actually, you must make Player, Item and Pokemon conform to NSCoding, not NSCoder.

Conforming to NSCoding basically lets you define a way to encode and decode an object of the conforming class, while an NSCoder subclass does the actual encoding and/or decoding.

You want to archive a Player:

let encodedData = NSKeyedArchiver.archivedDataWithRootObject(Player.User.Gold)

However, since Player, Item and Pokemon don't conform to NSCoding, NSKeyedUnarchiver has no idea how to encode them! As a result, an error appears.

Sign up to request clarification or add additional context in comments.

2 Comments

I think I understand! I'll mess with it and see if it works, just dreading encoding all that whole pokemon class
works perfectly! I was stuck on this for so long, thank you very much!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.