Экономия времени в UserDefaults

Я работаю над небольшой игрой. Когда пользователь запускает игру и закрывает ее, приложение сохраняет временную метку, поэтому, когда он возвращается, оно может рассчитать в секундах, как долго он отсутствовал.

Моя проблема в том, что при повторном открытии приложение вылетает. Я вижу, что это проблема преобразования, но я пробовал разные вещи, которые не работали.

Так что моя последняя надежда — переполнение стека. :-)

Мой код выглядит следующим образом: в файле AppDelegate.swift он сохраняет дату:

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

И когда пользователь повторно открывает приложение (все еще AppDelegate.swift)

GameScene().calculateTimeLeft()

И, наконец, мой 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()
}

Изменить:

Забыл вставить лог:

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).

person doingSomeSwiftHere    schedule 29.08.2017    source источник
comment
Если я использую упрощенную версию вашего кода на игровой площадке, она работает нормально. (Является ли appData просто UserDefaults.standard?)   -  person Phillip Mills    schedule 29.08.2017
comment
Хм, это действительно очень странно. Да, я просто сделал appData как ярлык :-)   -  person doingSomeSwiftHere    schedule 29.08.2017
comment
Может быть, вы случайно пишете что-то еще, используя ключ GameData.lastTimeActiveStamp? После того, как вы написали дату.   -  person algrid    schedule 29.08.2017
comment
@user2026507 user2026507 - Я предлагаю установить точку останова, которая позволит вам увидеть, какой тип данных (и контент) возвращается из appData.object.   -  person Phillip Mills    schedule 29.08.2017
comment
Вы устанавливаете GameData.lastTimeActiveStamp откуда-то еще и когда вы его сбрасываете?   -  person Vini App    schedule 30.08.2017


Ответы (2)


Этот код работал для меня:

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

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

Вместо принудительного развертывания переменных используйте больше функций, таких как if let, guard let и т. д. Это позволит избежать сбоя приложения в случае сбоя приведения.

person Felipe Koji Waku    schedule 29.08.2017

Я бы не рекомендовал сохранять Date() как значение внутри UserDefaults, я бы попробовал использовать что-то, что можно было бы легче сериализовать туда и обратно, например, строки или целые числа.

Попробуйте заменить:

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

с

appData.set(Date().timeIntervalSince1970, forKey: GameData.lastTimeActiveStamp)
person mango    schedule 29.08.2017
comment
Класс UserDefaults предоставляет удобные методы для доступа к распространенным типам, таким как числа с плавающей запятой, двойные числа, целые числа, логические значения и URL-адреса. Объект по умолчанию должен быть списком свойств, то есть экземпляром (или для коллекций, комбинацией экземпляров): NSData, NSString, NSNumber, NSDate, NSArray или NSDictionary. developer.apple.com/documentation/foundation/userdefaults - person Leo Dabus; 29.08.2017