0
1

iOS / macOSの構造体をUserDefaultsに保存する

Posted at

データやパラメータをひとかたまりにした構造体(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で保存するためのキーを複数用意しておけば対応できます。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1