【Swift】NSKeyedArchiverでクラスをそのままUserDefaultsに保存する
この記事からわかること
- Swift/NSKeyedArchiverでクラスをそのまま保存する方法
- NSKeyedArchiver/NSKeyedUnarchiverクラスとは?
- 独自のクラスをData型に変換する方法
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
参考文献:公式リファレンス:Caching on Swift Using NSKeyedArchiver
NSKeyedArchiverクラスとは?
class NSKeyedArchiver : NSCoder
NSKeyedArchiver
はオブジェクトのデータをキーによって参照されるアーカイブに保存するエンコーダークラスです。オブジェクトをファイルなどへの保存に適した、アーキテクチャに依存しない形式にエンコードする方法を提供しています。
独自に定義したクラスも構造を保ったままData
型にエンコードすることでコード内での扱いやすさも向上します。
NSKeyedUnarchiverクラスとは?
class NSKeyedUnarchiver : NSCoder
NSKeyedUnarchiver
はキーによって参照されるアーカイブからデータを復元するデコーダークラスです。NSKeyedArchiver
と逆側の処理を担っています。
クラスをそのままUserDefaultsに保存する
この2つのクラスを使用することで独自に定義したクラスをUserDefaultsに保存し、取得することができるようになります。
流れ
- 独自クラスの定義
- NSObject/NSCodingへの準拠
- encode(with coder: NSCoder)/required init?(coder: NSCoder)の実装
- クラスをエンコードしてアーカイブを作成しUserDefaultsに保存
- UserDefaultsから取り出したアーカイブをデコードしてクラスに変換
まずは独自のクラスを定義します。
class User {
var id:Int
var name:String
init(id: Int, name: String) {
self.id = id
self.name = name
}
}
NSObject
とNSCoding
に準拠させます。NSCoding
に準拠させたことでencode(with coder: NSCoder)
メソッド(エンコード処理用)とrequired init?(coder: NSCoder)
(デコード処理用)の実装が必須となります。
class User:NSObject,NSCoding {
var id:Int
var name:String
init(id: Int, name: String) {
self.id = id
self.name = name
}
func encode(with coder: NSCoder) {
coder.encode(id,forKey: "id")
coder.encode(name,forKey: "name")
}
required init?(coder: NSCoder) {
id = coder.decodeObject(forKey: "id") as! Int
name = coder.decodeObject(forKey: "name") as! String
}
}
あとは保存したいクラスをアーカイブに変換しUserDefaultsに保存する処理とUserDefaultsに保存されているアーカイブをデコードしてクラスに変換する処理を書けば完成です。
struct ContentView: View {
var userDefaults = UserDefaults.standard
func setUser(){
let user = User(id: 1, name: "ame")
let data = try? NSKeyedArchiver.archivedData(withRootObject: user, requiringSecureCoding: false)
userDefaults.set(data, forKey: "user")
}
func getUser(){
let obj = userDefaults.data(forKey: "user")!
let user = NSKeyedUnarchiver.unarchiveObject(with: obj) as! User
print(user.id)
print(user.name)
}
var body: some View {
VStack{
Button {
getUser()
} label: {
Text("getUser")
}
Button {
setUser()
} label: {
Text("setUser")
}
}
}
}
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。