データやパラメータをひとかたまりにした構造体(struct)を丸ごとUserDefaultsに保存し、アプリ起動時に読み出す必要が出てきました。
そのためには構造体の定義時、Codable
に対応させる必要があります。
struct CEngineParameter: Codable {
private var _parameterType = EngineType.water
public var isEngineEnable = true
public var differenceHeight = Float(5)
public var differenceWidth = 32
...
...
}
このように構造体を定義すると、Codable
に対応したイニシャライザの実装が求められます。
下記のように、対応したイニシャライザを記述します。
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self._parameterType = try container.decode(EngineType.self, forKey: ._parameterType)
self.isEngineEnable = try container.decode(Bool.self, forKey: .isEngineEnable)
self.differenceHeight = try container.decode(Float.self, forKey: .differenceHeight)
self.differenceWidth = try container.decode(Int.self, forKey: .differenceWidth)
...
...
}
_parameterTypeというプロパティはenum型です。
enum型も下記のようにCodableに対応させれば保存可能です。
enum EngineType: Codable {
case water
case air
}
この構造体の読み出し・保存がちょっと複雑です。
そこで、構造体に読み出し・保存のメソッドを実装し、使いやすくします。
public static func load(forKey: String) -> CEngineParameter? {
if let loadValue = UserDefaults.standard.data(forKey: forKey) {
let decoder = JSONDecoder()
if let value = try? decoder.decode(CEngineParameter.self, from: loadValue) {
return value
} else {
return nil
}
} else {
return nil
}
}
public func save(forKey: String) {
let encoder = JSONEncoder()
if let encodedValue = try? encoder.encode(self) {
UserDefaults.standard.set(encodedValue, forKey: forKey)
UserDefaults.standard.synchronize()
}
}
構造体のオブジェクトが複数あっても、UserDefaultsで保存するためのキーを複数用意しておけば対応できます。