0


I am new to swift, and I am trying to build a game which will include a top 5 players name and score, if i just add the players to an array and than restart the game it "deletes" the players, so i am trying to use NSUserDefaults(i need to store just 5 strings and 5 integers), it does not work no matter what, the code is:

class scoreController: UITableViewController {

    var playersArray:[Player] = [Player]()

    var nameFromGame = "" //name from game vc
    var timeFromGame = 0 //time from game vc

    let tmpPlayer = Player(playerName: "", scoreTime: 0)
    let playerDefaults = NSUserDefaults.standardUserDefaults()

    override func viewDidLoad() {
        super.viewDidLoad()

        let player1 = Player(playerName: "Bil", scoreTime: 50)
        let player2 = Player(playerName: "Bob", scoreTime: 100)


        playersArray.append(player1)
        playersArray.append(player2)

         tmpPlayer.playerName = nameFromGame
         tmpPlayer.scoreTime = timeFromGame
         playersArray.append(tmpPlayer)

         playerDefaults.setObject(playersArray[11], forKey: "players")

            print(playersArray )
        }
    }

I am just trying to save this for now and it crashes, does anyone know why? and also how can i store this in my app so it will save the data?

thank you!

Coder123
  • 784
  • 2
  • 8
  • 29

3 Answers3

2

Your player objects probably are the problem here. You must implement two methods in your player class (I am no swift master but it's probaby the same mistake):

- (void)encodeWithCoder:(NSCoder *)encoder;
- (id)initWithCoder:(NSCoder *)decoder;

That should work for you. Hope it helps!!

PD: check this answer How to store custom objects in NSUserDefaults

Community
  • 1
  • 1
facumenzella
  • 559
  • 3
  • 10
  • i guess those are objective c methods.. do you know the swift ones? – Coder123 Jun 04 '16 at 21:07
  • 1
    Here...https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Protocols/NSCoding_Protocol/#//apple_ref/occ/intfm/NSCoding/encodeWithCoder: Hope it helps!! – facumenzella Jun 06 '16 at 20:13
1

Your Player class needs to conform to NSCoding, and you'll need to store an archived data of your players array and unarchive it when extracting out the data.

Class:

class Player: NSObject, NSCoding {
    var playerName: String
    var scoreTime: Int

    init(playerName: String, scoreTime: Int) {
        self.playerName = playerName
        self.scoreTime = scoreTime
    }

    func encodeWithCoder(aCoder: NSCoder) {
        aCoder.encodeInteger(scoreTime, forKey: "score_time")
        aCoder.encodeObject(playerName, forKey: "player_name")
    }

    required convenience init?(coder decoder: NSCoder) {
        guard let playerName = decoder.decodeObjectForKey("player_name") as? String else {
            return nil
        }
        self.init(playerName: playerName, scoreTime: decoder.decodeIntegerForKey("score_time"))
    }
}

NSUserdefaults & Archiving/Unarchiving :

    let player1 = Player(playerName: "Bil", scoreTime: 50)
    let player2 = Player(playerName: "Bob", scoreTime: 100)

    let playersArray = [player1, player2]
    let playersData  = NSKeyedArchiver.archivedDataWithRootObject(playersArray)

    let defaults = NSUserDefaults.standardUserDefaults()
    defaults.setObject(playersData, forKey: "players")
    defaults.synchronize()

    if let playersArrayData = defaults.objectForKey("players") as? NSData {
        let unarchivedPlayers = NSKeyedUnarchiver.unarchiveObjectWithData(playersArrayData) as! [Player]
        print(unarchivedPlayers)
    }

Hope this helps, please remember to choose answer and up-vote if this solves your question.

NSDavidObject
  • 328
  • 2
  • 5
  • 13
0

You need to could call

playerDefaults.synchronize()

to save the data in the defaults.

EDIT
As facumenzella says, your other problem is storing custom class objects in the defaults. To solve that you need to implement methods in the custom Player class that tell it how to be converted to data. Then you should serialize the object before you store it in the defaults.

mginn
  • 16,036
  • 4
  • 26
  • 54
  • No, you don't need, the method is called periodically by the operating system. – vadian Jun 04 '16 at 21:03
  • However, if he is accessing the defaults soon after setting them, he should synchronize after the change. Also, there is always the chance that the app could crash or be stopped by the user, in which case a period synchronization may not occur. – mginn Jun 04 '16 at 21:05