Как обрабатывать миграцию моделей при сохранении их в UserDefault? - PullRequest
1 голос
/ 20 марта 2019

У меня есть объект с именем User, который соответствует Codable, представленному в Swift4.

например, этот объект раньше был

struct User: Codable {
    var firstName: String
}

и мы используем PropertyListDecoder().decode(User.self, from: data) и PropertyListEncoder().encode(value) для кодирования User в Data и декодирования Data в User.

Теперь мы обновили объект до

struct User: Codable {
    var firstName: String
    var isLoggedIn: Bool
}

Если наше приложение обновлено из старого приложения, в котором хранится старый Data, хранящийся в UserDefault. Первое, что приложение сделает после обновления, это извлекает Data и пытается декодировать в User с помощью PropertyListDecoder().decode(User.self, from: data). Но выдает ошибку:

po PropertyListDecoder().decode(User.self, from: data)
▿ DecodingError
  ▿ keyNotFound : 2 elements
    - .0 : CodingKeys(stringValue: "isLoggedIn", intValue: nil)
    ▿ .1 : Context
      - codingPath : 0 elements
      - debugDescription : "No value associated with key CodingKeys(stringValue: \"isLoggedIn\", intValue: nil) (\"isLoggedIn\")."
      - underlyingError : nil

Есть идеи, как бы я справился с миграцией модели в этом случае? Я знаю, что для Coredata есть несколько простых способов справиться с этим, но я понятия не имею, как осуществить это в UserDefault.

1 Ответ

1 голос
/ 20 марта 2019

Вы можете реализовать инициализатор декодирования и установить значение по умолчанию для isLoggedIn, если его нет:

struct User: Codable {
  var firstName: String
  var isLoggedIn: Bool

  enum Keys: CodingKey {
    case firstName
    case isLoggedIn
  }

  public init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: Keys.self)
    firstName = try container.decode(String.self, forKey: .firstName)
    isLoggedIn = try container.decodeIfPresent(Bool.self, forKey: .isLoggedIn) ?? false
  }
}
...