UserDefaultsにCodable(struct)を保存する
「えー!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)
}
}
}
}
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)
}
}
}
}
こんな感じでいつでも呼び出せるようにしたら便利そうですね。
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)を保存する方法を調べてみました。
ユーザー周りの設定を外部のデータベース上に保存しているときとかに結構使えそうですね。
参考文献
Author And Source
この問題について(UserDefaultsにCodable(struct)を保存する), 我々は、より多くの情報をここで見つけました https://qiita.com/tanaka-tt/items/b9bf8b1acc9f183dd1e6著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .