Saving time in UserDefaults

9k views Asked by At

I'm working on a little game. When the user has a game going and shuts down the game, the app saves a timestamp so when he returns it can calculate, in seconds, for how long time he was away.

My problem is, that when the app re-opens it crashes. I can see that it's a conversion issue, but I tried various things that did not work.

So my last hope is Stack Overflow. :-)

My code is as following: In the AppDelegate.swift file it saves the date:

appData.set(Date(), forKey: GameData.lastTimeActiveStamp)

And when the user re-opens the app (still AppDelegate.swift)

GameScene().calculateTimeLeft()

And finally my GameScene.swift:

let timeSinceActive = appData.object(forKey: GameData.lastTimeActiveStamp)!
/* Check the difference */
let elapsedTime = Date().timeIntervalSince(timeSinceActive as! Date)
/* Convert this to seconds */
let timeSpentAwayInSeconds = Int(elapsedTime)
/* Find out how many seconds the user had left when he quitted the game */
let currentTimeLeft = appData.integer(forKey: GameData.currentTimeLeft)
/* If the time spent away is larger than the seconds there was left, the game is over */
if timeSpentAwayInSeconds > currentTimeLeft {
    /* Game over */
    appData.set(0, forKey: GameData.currentTimeLeft)

    GameOver()
}

Edit:

Forgot to paste the log:

Could not cast value of type '__NSCFData' (0x1b8c90f30) to 'NSDate' (0x1b8c91b10).
2017-08-29 20:16:49.533396+0200 Sleepy[929:226885] Could not cast value of type '__NSCFData' (0x1b8c90f30) to 'NSDate' (0x1b8c91b10).
2

There are 2 answers

0
Felipe Koji Waku On

This code worked for me:

let app = UserDefaults.standard
let date = Date()
app.set(date, forKey: "date")

if let date2 = app.object(forKey: "date") as? Date {
  Date().timeIntervalSince(date2)
}

Instead of force unwrapping the variables use more features like if let, guard let, etc. This avoid crashing your application if the cast fails

1
mango On

I wouldn't recommend saving Date() as a value inside of UserDefaults, I'd try going for something that can more easily be serialized back and forth like strings or ints.

Try replacing:

appData.set(Date(), forKey: GameData.lastTimeActiveStamp)

with

appData.set(Date().timeIntervalSince1970, forKey: GameData.lastTimeActiveStamp)