Posted at

[iOS, Swift4] カスタムクラスをData型に変換する(UserDefaultsにカスタムクラスの配列を保存する)

More than 1 year has passed since last update.


カスタムクラスをData型に変換する必要性

例えばUserDefaultsを使用する場合、カスタムオブジェクトをNSDataに変換する必要があります :)

なぜかというと、UserDefaultsで保存できる型は NSData, NSString, NSNumber, NSDate, NSArray, NSDictionary となっているからです。

これ以外の型を保持させたい場合は一旦NSData型に変換してから保持し、読み込む際はNSData型として読み込んだ後に型変換を行う必要があります。

以下では「UserDefaultsにてカスタムクラスの配列を保存、読み込む」という具体的なケースで、Swift4でカスタムクラスをData型に変換する処理を見ていきます😄


流れ

iOS ではシリアライズすることをアーカイブ、デシリアライズすることをアンアーカイブといいます。

アーカイブのためのクラスとして NSKeyedArchiver クラス

アンアーカイブのためのクラスとして NSKeyedUnarchiver クラスがあります。

概要図 2018-05-04 13.26.58.png


UserDefaultsにカスタムクラスの配列を保存・読み込みをする

まず、独自に作成するカスタムクラスを定義します。

<ポイント>

NSObject, NSCodingを継承する

エンコード、デコード処理を記述する

class SomeObj: NSObject, NSCoding {

var word: String!
var date: String!

init(word: String, date: String) {
self.word = word
self.date = date
}

required init?(coder aDecoder: NSCoder) {
self.word = aDecoder.decodeObject(forKey: "word") as! String
self.date = aDecoder.decodeObject(forKey: "date") as! String
}

func encode(with aCoder: NSCoder) {
if let word = word { aCoder.encode(word, forKey: "word") }
if let date = date { aCoder.encode(date, forKey: "date") }
}
}

保存処理ではNSKeyedArchiver.archivedDataを使用します


var someObjArray = [SomeObj]()
let someObj = SomeObj(word: "hoge", date: "2000/01/01")

someObjArray.insert(someObj, at: 0)

UserDefaults.standard.set(NSKeyedArchiver.archivedData(withRootObject: someObjArray), forKey: "someObjs")

読み込み処理では、一度Data型で読み込んだものをNSKeyedUnarchiver.unarchiveObjecを使用してアンアーカイブ(デシリアライズ)します


func loadSomeObjs() -> [someObj]?{
if let loadedData = UserDefaults().data(forKey: "someObjs") {
let someObjs = NSKeyedUnarchiver.unarchiveObject(with: loadedData) as! [SomeObj]
return someObjs
}else {
return nil
}
}

これでUserDefaultsにカスタムクラスの配列を保存したり、読み込んだりできるようになります!