невозможно декодировать сохраненную информацию в Swift - PullRequest
0 голосов
/ 25 февраля 2019

Я пытаюсь сохранить очень простой объект с помощью NSKeyedArchiver в swift, и я вижу, что он сохраняет правильно со значениями, но всякий раз, когда он пытается декодировать сохраненные данные, он терпит неудачу.Я новичок в Swift, и я пробовал гуглить и os_log (ing) все, но я не вижу, в чем проблема.Вот объект, который я пытаюсь сохранить ...

class TrackedAmount: NSObject, NSCoding {
  var cups: Int
  var fraction: Float?

  struct PropertyKey {
    static let cups = "cups"
    static let fraction = "fraction"
  }
  init?(cups: Int, fraction: Float?) {
    os_log("Running init? function", log: .default, type: .debug)
    if(cups < 0) {
      os_log("Cups less than 0. Returning nil", log: .default, type: .debug)
      return nil
    }
    self.cups = cups
    self.fraction = fraction
  }

  required convenience init? coder aDecoder: NSCoder) {
    os_log("Running required convenience init? function", log: .default, type: .debug)
    guard let cups = aDecoder.decodeObject(forKey: PropertyKey.cups) as? Int else {
      os_log("Unable to decode cups", log: .default, type: .debug)
      return nil
    }
    guard let fraction = aDecoder.decodeObject(forKey: PropertyKey.fraction) as? Float else {
      os_log("Unable to decode fraction", log: .default, type: .debug)
      return nil
    }
    self.init(cups: cups, fraction: fraction)
  }

  func encode(with aCoder: NSCoder) {
    aCoder.encode(cups, forKey: PropertyKey.cups)
    aCoder.encode(fraction, forKey: PropertyKey.fraction)
  }

Затем в моем ViewController я пытаюсь получить и сохранить их вот так ...

 private func saveAmount() {
    trackedToday = TrackedAmount(cups: selectedCups, fraction: selectedFraction)
    print("data.... cups: " + String(trackedToday!.cups) + " fractions: " + String(trackedToday!.fraction!))
    let fullPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("dailytracked")
    do {
      let data = try NSKeyedArchiver.archivedData(withRootObject: trackedToday!, requiringSecureCoding: false)
      try data.write(to: fullPath)
    } catch {
      os_log("Unable to save tracking amount", log: .default, type: .debug)
    }
  }

  private func loadDailyTracked() -> TrackedAmount? {
    let fullPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("dailytracked")
    if let nsData = NSData(contentsOf: fullPath) {
      do {
        let data = Data(referencing: nsData)
        if let loadedData = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? TrackedAmount {
          os_log("it finally worked", log: .default, type: .debug)
          return loadedData
        }
      } catch {
        os_log("Couldn't read from file", log: .default, type: .debug)
        return nil
      }
    return nil
  }

Этосохранение правильно, но всякий раз, когда я пытаюсь запустить метод loadDailyTracked (), я получаю следующее в разделе вывода в xcode ...

Запуск необходимого удобства init?функция

Невозможно декодировать чашки

Я не могу понять, почему он не может декодировать чашки, я знаю, что данные сохраняются, так как ни один из журналов не показываетлюбой сбой, за исключением случаев, когда он пытается прочитать из сохраненных данных.Я даже записал информацию перед сохранением, и она показывает правильные данные.У кого-нибудь есть идеи?Я действительно новичок в IOS и Swift, и я просто не могу понять это.Спасибо.

* Дополнительное примечание: если вам нужно больше кода или информации, я рад предоставить ее, я просто пытался не допустить, чтобы сообщение было слишком большим, если это не нужно.

1 Ответ

0 голосов
/ 25 февраля 2019

В терминах NSCoder скалярные типы, такие как Int и Float, являются , а не объектами, а выделенные методы не возвращают необязательные значения

required convenience init? coder aDecoder: NSCoder) {
    os_log("Running required convenience init? function", log: .default, type: .debug)
    let cups = aDecoder.decodeInteger(forKey: PropertyKey.cups)
    let fraction = aDecoder.decodeFloat(forKey: PropertyKey.fraction)
    self.init(cups: cups, fraction: fraction)
}

NSCoding inСвифт довольно тяжелый.Настоятельно рекомендуется использовать протокол Codable для сериализации структур и классов.

...