「えー!UserDefaultsにstructを保存できるんですかーーー?」って思ったので調べてみました。
バージョン
Xcode: v11.3
Swift: v5.3.2
対象読者
- UserDefaultsを使ったことのある人
- UserDefaultsにstructを保存できることを知らなかった人
実装
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)を保存する方法を調べてみました。
ユーザー周りの設定を外部のデータベース上に保存しているときとかに結構使えそうですね。