基本的な流れ
//インスタンスの生成
let userDefaults = UserDefaults.standard
//キーを「test」に指定して、文字列を保存
userDefaults.set("1234", forKey: "test")
//明示的な同期指示(キャッシュメモリからplist形式への保存)
userd.synchronize()
//「test」キーに対応するString型の保存された値を取り出す
let val = userDefaults.string(forKey: "test")
アプリ開発時の使い方
@IBOutlet weak var textField: UITextField!
@IBAction func tapActionButton(_ sender: AnyObject) {
let userDefaults = UserDefaults.standard
//保存
userDefaults.set(textField.text, forKey: "test")
userDefaults.synchronize()
}
override func viewDidLoad() {
super.viewDidLoad()
let userDefaults = UserDefaults.standard
//取り出し
if let value = userDefaults.string(forKey: "test") {
textField.text = value
}
}
独自クラスを保存する
UserDefaultsはNSData型の保存をサポートしているので、独自クラスを一旦NSData型にすることでUserDefaultsに保存することができます。
シリアライズ
オブジェクトの内容をバイナリデータに変換すること。
シリアライズするためのクラス
NSKeyedArchiver
NSKeyedArchiverクラスに呼び出される独自クラス側に実装するメソッド
NSCodingプロトコルのencodeメソッド
public func encode(with aCoder: NSCoder)
NSKeyedArchiverクラスでのシリアライズ処理をする時は、独自クラス側に決められたメソッドを実装し、この実装したメソッドがNSKeyedArchiverクラスに呼び出されることになります。この決められたメソッドはNSCodingプロトコルのencodeメソッドです。
NSCodingプロトコル
独自クラスをUserDefaultsに保存するときは必ずNSCodingプロトコルを継承します。
それは、このプロトコルにシリアライズ、デシリアライズを行うメソッドが定義されているからです。
メソッドの引数はNSCoder型で、NSCoderクラスにはシリアライズ、デシリアライズに関するメソッド群が定義されています。
また、シリアライズの対象となるクラス(独自クラス)はNSObjectクラスを継承する必要がある。
※)厳密にはNSKeyedArchiverクラスがシリアライズ処理そのものを行うのではなく、呼び出された独自クラスに実装されているNSCodingプロトコルのencodeメソッド内で独自クラスのシリアライズ処理は行われます。
引数のNSCoderクラスのシリアライズに関するメソッドを用いて処理を行います。
NSKeyedArchiverクラスの役割はencodeメソッドの呼び出しです。
デシリアライズに関しても同じです。
class Myclass: NSObject, NSCoding{
var valueString: String?
//引数なしのイニシャライザを設定。引数なしでのインスタンスを生成しない場合はなくてもよい
override init(){}
//NSKeyedArchiverに呼び出されるエンコードメソッド
func encode(with aCoder: NSCoder) {
//引数で受け取ったNSCoderクラスにはシリアライズ、デシリアライズに
//関するメソッド群が定義されている
//キーを指定してオブジェクト(値)をエンコード(シリアライズ)
aCoder.encode(valueString, forKey: "valueString")
}
//NSKeyedUnArchiverに呼び出されるデコードメソッド
required init?(coder aDecoder: NSCoder) {
//指定したキーの値をデコード(デシリアライズ)。今回は保存した値が文字列なのでstringにキャストし、
//変数に収める
valueString = aDecoder.decodeObject(forKey: "valueString") as? String
}
}
※)プロトコルのイニシャライザをオーバーライドする時の修飾子は override ではなくrequired。
デシリアライズ
バイナリデータからオブジェクトを復元すること。
デシリアライズするためのクラス
NSKeyedUnArchiver
NSKeyedArchiverクラスに呼び出される独自クラス側に実装するメソッド
NSCodingプロトコルのinitメソッド
内容はシリアライズと同じ。
required init?(coder aDecoder: NSCoder)
実装コードは上記シリアライズ処理に記述。
メインのシリアライズとデシリアライズの処理
シリアライズ
NSKeyedArchiverクラスのarchivedDataメソッドにてシリアライズを行う。
※)厳密にはNSCodingプロトコルのencodeメソッドの呼び出し。
archivedData(withRootObject: シリアライズ対象のデータ)
デシリアライズ
NSKeyedUnarchiverクラスのunarchiveObjectメソッドにてデシリアライズを行う。
※)厳密にはNSCodingプロトコルのinitメソッドの呼び出し。
unarchiveObject(with: デシリアライズ対象のデータ)
● 使い方
//デシリアライズしたデータを変数に収める
let unarchiveData = NSKeyedUnarchiver.unarchiveObject(with: デシリアライズ対象のデータ)
アプリ開発時の使い方
※独自クラスを上記に記述
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//UserDefaultsのインスタんすの生成
let userDefaults = UserDefaults.standard
//独自クラスのインスタンスを生成
let data = MyClass()
data.valueString = "test"
//**************シリアライズ処理****************************************
//シリアライズ対象データは独自クラスのMyClassのインスタンス
let archiveData = NSKeyedArchiver.archivedData(withRootObject: data)
//シリアライズしてNSData型になったデータを保存
userDefaults.set(archiveData, forKey: "data")
//更新
userDefaults.synchronize()
//**************デシリアライズ処理***************************************
//キーを指定してデータをNSData型に変換して取り出す。
//userDefaultsには最終的にはplist形式(xml)で保存されるため,
//unarchiveObjectメソッドの引数の型がData型のためキャストする
if let storedData = userDefaults.object(forKey: "data") as? Data{
//取り出したデータをデシリアライズし、保存する前の型にキャストする
if let unarchiveData = NSKeyedUnarchiver.unarchiveObject(with: storedData) as? MyClass{
//取り出したデータ(MyClassクラスのインスタンス)のプロパティの文字列を表示させる
if let valueString = unarchiveData.valueString {
//「test」を表示
print(valueString)
}
}
}
}