LoginSignup
0
1

More than 3 years have passed since last update.

UserDefaultsにCodable(struct)を保存する

Last updated at Posted at 2021-04-20

「えー!UserDefaultsにstructを保存できるんですかーーー?」って思ったので調べてみました。

バージョン

Xcode: v11.3
Swift: v5.3.2

対象読者

  • UserDefaultsを使ったことのある人
  • UserDefaultsにstructを保存できることを知らなかった人

実装

UIViewController.swift
import UIKit

struct Settings: Codable {
    var displayName: String
    var colorTheme: String
}

class ViewController: UIViewController {
    let defaults = UserDefaults.standard
    override func viewDidLoad() {
        super.viewDidLoad()
        let settings = Settings(displayName: "tt", colorTheme: "Red")
        let encoder = JSONEncoder()
        if let encoded = try? encoder.encode(settings) {
            defaults.set(encoded, forKey: "settings")
        }
        if let settings = defaults.object(forKey: "settings") as? Data {
            let decoder = JSONDecoder()
            if let loadedSettings = try? decoder.decode(Settings.self, from: settings) {
                print(loadedSettings)
            }
        }
    }
}

こんな感じでいつでも呼び出せるようにしたら便利そうですね。

UIViewController.swift
import UIKit

struct Settings: Codable {
    var displayName: String
    var colorTheme: String
}

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let settings = Settings(displayName: "UserA", colorTheme: "Red")
        let encoder = JSONEncoder()
        if let encoded = try? encoder.encode(settings) {
            UserDefaults.standard.set(encoded, forKey: "settings")
        }

        let savedSettings = getSettings()!
        print(savedSettings.colorTheme)

    }

    func getSettings() -> Settings? {
        if let settings = UserDefaults.standard.object(forKey: "settings") as? Data {
            let decoder = JSONDecoder()
            if let loadedSettings = try? decoder.decode(Settings.self, from: settings) {
                return loadedSettings
            } else {
                print("decode failed")
            }
        } else {
            print("UserDefaults object named settings is not found")
        }
        return nil
    }
}

解説

set(_: forKey:)

UserDefaultsにはset(_ value: Any?, forKey: String)が提供されています。「Anyといっても何でも保存できんの?」と思って公式ドキュメントを調べてみると

The value parameter can be only property list objects: NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. For NSArray and NSDictionary objects, their contents must be property list objects. For more information, see What is a Property List? in Property List Programming Guide.

NSData, NSString, NSNumber, NSDate, NSArray, NSDictonaryに準拠してるオブジェクトなら保存できるみたいです。

DataとNSData

上のコードのencodeという変数の型を調べてみるとDataになっており、set(_: forKey:)NSDataしか保存できないのでは?と思って調べてみました。参考リンクによると

The major change between both is just the name. However, there are some methods that are different. See the link above for these changes in detail.

ということで、基本的には名前にしか差が無いみたいです。

細かい差としては

There is rather big change. Data is Swift native type and it is a struct, while NSData is an object. Using Data allows us to use one type instead of using NSData for immutable data and NSMutableData for mutable data.

ということで、Dataを使うことで、immutableのデータにはNSDataをmutableなデータにはNSMutableDataを使う必要がないみたいです。

終わりに

今回はUserDefaultsにCodable(struct)を保存する方法を調べてみました。

ユーザー周りの設定を外部のデータベース上に保存しているときとかに結構使えそうですね。

参考文献

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